0020716: Eliminate usage of "config.h" header file
[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
a174a3c5 115 if (theIs2d)
116 {
117 glRasterPos2f (0.0f, 0.0f);
118 }
119 else
120 {
121 glRasterPos3f (0.0f, 0.0f, 0.0f);
122 }
123
124 GLubyte aZero = 0;
125 glBitmap (1, 1, 0, 0, 0, 0, &aZero);
126
127 // Standard GL2PS's alignment isn't used, because it doesn't work correctly
128 // for all formats, therefore alignment is calculated manually relative
129 // to the bottom-left corner, which corresponds to the GL2PS_TEXT_BL value
105aae76 130 gl2psTextOpt (theText.ToCString(), aPsFont, (GLshort)theHeight, GL2PS_TEXT_BL, theAspect.Angle());
a174a3c5 131 }
132#endif
133
134};
135
136// =======================================================================
137// function : OpenGl_Text
138// purpose :
139// =======================================================================
140OpenGl_Text::OpenGl_Text()
141: myWinX (0.0f),
142 myWinY (0.0f),
143 myWinZ (0.0f),
144 myScaleHeight (1.0f),
145 myPoint (0.0f, 0.0f, 0.0f),
146 myIs2d (false)
147{
148 myParams.Height = 10;
149 myParams.HAlign = Graphic3d_HTA_LEFT;
150 myParams.VAlign = Graphic3d_VTA_BOTTOM;
2166f0fa
SK
151}
152
a174a3c5 153// =======================================================================
154// function : OpenGl_Text
155// purpose :
156// =======================================================================
b64d84be 157OpenGl_Text::OpenGl_Text (const Standard_Utf8Char* theText,
158 const OpenGl_Vec3& thePoint,
159 const OpenGl_TextParam& theParams)
a174a3c5 160: myWinX (0.0f),
161 myWinY (0.0f),
162 myWinZ (0.0f),
163 myScaleHeight (1.0f),
164 myExportHeight (1.0f),
165 myParams (theParams),
b64d84be 166 myString (theText),
a174a3c5 167 myPoint (thePoint),
168 myIs2d (false)
169{
170 //
171}
2166f0fa 172
a174a3c5 173// =======================================================================
174// function : SetPosition
175// purpose :
176// =======================================================================
177void OpenGl_Text::SetPosition (const OpenGl_Vec3& thePoint)
2166f0fa 178{
a174a3c5 179 myPoint = thePoint;
2166f0fa
SK
180}
181
a174a3c5 182// =======================================================================
183// function : SetFontSize
184// purpose :
185// =======================================================================
186void OpenGl_Text::SetFontSize (const Handle(OpenGl_Context)& theCtx,
187 const Standard_Integer theFontSize)
188{
189 if (myParams.Height != theFontSize)
190 {
10b9c7df 191 Release (theCtx.operator->());
a174a3c5 192 }
193 myParams.Height = theFontSize;
194}
195
196// =======================================================================
197// function : Init
198// purpose :
199// =======================================================================
200void OpenGl_Text::Init (const Handle(OpenGl_Context)& theCtx,
201 const Standard_Utf8Char* theText,
202 const OpenGl_Vec3& thePoint)
203{
10b9c7df 204 releaseVbos (theCtx.operator->());
a174a3c5 205 myIs2d = false;
206 myPoint = thePoint;
207 myString.FromUnicode (theText);
208}
209
210// =======================================================================
211// function : Init
212// purpose :
213// =======================================================================
214void OpenGl_Text::Init (const Handle(OpenGl_Context)& theCtx,
215 const Standard_Utf8Char* theText,
216 const OpenGl_Vec3& thePoint,
217 const OpenGl_TextParam& theParams)
218{
219 if (myParams.Height != theParams.Height)
220 {
10b9c7df 221 Release (theCtx.operator->());
a174a3c5 222 }
223 else
224 {
10b9c7df 225 releaseVbos (theCtx.operator->());
a174a3c5 226 }
227 myIs2d = false;
228 myParams = theParams;
229 myPoint = thePoint;
230 myString.FromUnicode (theText);
231}
2166f0fa 232
a174a3c5 233// =======================================================================
234// function : Init
235// purpose :
236// =======================================================================
237void OpenGl_Text::Init (const Handle(OpenGl_Context)& theCtx,
238 const TCollection_ExtendedString& theText,
239 const OpenGl_Vec2& thePoint,
240 const OpenGl_TextParam& theParams)
2166f0fa 241{
a174a3c5 242 if (myParams.Height != theParams.Height)
243 {
10b9c7df 244 Release (theCtx.operator->());
a174a3c5 245 }
246 else
247 {
10b9c7df 248 releaseVbos (theCtx.operator->());
a174a3c5 249 }
250 myIs2d = true;
251 myParams = theParams;
252 myPoint.xy() = thePoint;
253 myPoint.z() = 0.0f;
254 myString.FromUnicode ((Standard_Utf16Char* )theText.ToExtString());
255}
256
257// =======================================================================
258// function : ~OpenGl_Text
259// purpose :
260// =======================================================================
261OpenGl_Text::~OpenGl_Text()
262{
263 //
264}
265
266// =======================================================================
267// function : releaseVbos
268// purpose :
269// =======================================================================
10b9c7df 270void OpenGl_Text::releaseVbos (OpenGl_Context* theCtx)
a174a3c5 271{
272 for (Standard_Integer anIter = 0; anIter < myVertsVbo.Length(); ++anIter)
273 {
274 Handle(OpenGl_VertexBuffer)& aVerts = myVertsVbo.ChangeValue (anIter);
275 Handle(OpenGl_VertexBuffer)& aTCrds = myTCrdsVbo.ChangeValue (anIter);
276
10b9c7df 277 if (theCtx)
a174a3c5 278 {
279 theCtx->DelayedRelease (aVerts);
280 theCtx->DelayedRelease (aTCrds);
281 }
282 aVerts.Nullify();
283 aTCrds.Nullify();
284 }
285 myTextures.Clear();
286 myVertsVbo.Clear();
287 myTCrdsVbo.Clear();
288 myVertsArray.Clear();
289 myTCrdsArray.Clear();
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 {
387 Handle(OpenGl_ShaderProgram) aProgram = aTextAspect->ShaderProgramRes (theWorkspace);
388
389 if (!aProgram.IsNull())
390 {
391 aProgram->BindWithVariables (aCtx);
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 }
400 else
401 {
402 OpenGl_ShaderProgram::Unbind (aCtx);
403 }
404 }
405
a174a3c5 406 // use highlight color or colors from aspect
407 if (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT)
408 {
409 render (theWorkspace->PrinterContext(),
30f0ad28 410 aCtx,
a174a3c5 411 *aTextAspect,
412 *theWorkspace->HighlightColor,
413 *theWorkspace->HighlightColor);
414 }
415 else
416 {
417 render (theWorkspace->PrinterContext(),
30f0ad28 418 aCtx,
a174a3c5 419 *aTextAspect,
420 aTextAspect->Color(),
421 aTextAspect->SubtitleColor());
422 }
2166f0fa 423
a174a3c5 424 // restore aspects
425 if (!aPrevTexture.IsNull())
426 {
427 theWorkspace->EnableTexture (aPrevTexture);
428 }
429}
2166f0fa 430
a174a3c5 431// =======================================================================
432// function : Render
433// purpose :
434// =======================================================================
435void OpenGl_Text::Render (const Handle(OpenGl_PrinterContext)& thePrintCtx,
436 const Handle(OpenGl_Context)& theCtx,
437 const OpenGl_AspectText& theTextAspect) const
438{
439 render (thePrintCtx, theCtx, theTextAspect, theTextAspect.Color(), theTextAspect.SubtitleColor());
440}
2166f0fa 441
a174a3c5 442// =======================================================================
443// function : setupMatrix
444// purpose :
445// =======================================================================
446void OpenGl_Text::setupMatrix (const Handle(OpenGl_PrinterContext)& thePrintCtx,
35e08fe8 447 const Handle(OpenGl_Context)& /*theCtx*/,
a174a3c5 448 const OpenGl_AspectText& theTextAspect,
449 const OpenGl_Vec3 theDVec) const
450{
451 // setup matrix
452 if (myIs2d)
bf75be98 453 {
a174a3c5 454 glLoadIdentity();
455 glTranslatef (myPoint.x() + theDVec.x(), myPoint.y() + theDVec.y(), 0.0f);
03e04ead 456 glScalef (1.0f, -1.0f, 1.0f);
457 glRotatef (theTextAspect.Angle(), 0.0, 0.0, 1.0);
2166f0fa
SK
458 }
459 else
460 {
a174a3c5 461 // align coordinates to the nearest integer
462 // to avoid extra interpolation issues
463 GLdouble anObjX, anObjY, anObjZ;
464 gluUnProject (std::floor (myWinX + (GLdouble )theDVec.x()),
465 std::floor (myWinY + (GLdouble )theDVec.y()),
466 myWinZ + (GLdouble )theDVec.z(),
467 (GLdouble* )THE_IDENTITY_MATRIX, myProjMatrix, myViewport,
468 &anObjX, &anObjY, &anObjZ);
469
470 glLoadIdentity();
471 glTranslated (anObjX, anObjY, anObjZ);
472 glRotated (theTextAspect.Angle(), 0.0, 0.0, 1.0);
473 if (!theTextAspect.IsZoomable())
474 {
475 #ifdef _WIN32
476 // if the context has assigned printer context, use it's parameters
477 if (!thePrintCtx.IsNull())
478 {
479 // get printing scaling in x and y dimensions
480 GLfloat aTextScalex = 1.0f, aTextScaley = 1.0f;
481 thePrintCtx->GetScale (aTextScalex, aTextScaley);
482
483 // text should be scaled in all directions with same
484 // factor to save its proportions, so use height (y) scaling
485 // as it is better for keeping text/3d graphics proportions
486 glScalef (aTextScaley, aTextScaley, aTextScaley);
487 }
488 #endif
489 glScaled (myScaleHeight, myScaleHeight, myScaleHeight);
490 }
491 }
492}
493
494// =======================================================================
495// function : drawText
496// purpose :
497// =======================================================================
35e08fe8 498
499void OpenGl_Text::drawText (const Handle(OpenGl_PrinterContext)& ,
a174a3c5 500 const Handle(OpenGl_Context)& theCtx,
35e08fe8 501 #ifdef HAVE_GL2PS
a174a3c5 502 const OpenGl_AspectText& theTextAspect) const
35e08fe8 503 #else
504 const OpenGl_AspectText& ) const
505 #endif
a174a3c5 506{
507#ifdef HAVE_GL2PS
508 if (theCtx->IsFeedback())
509 {
510 // position of the text and alignment is calculated by transformation matrix
511 exportText (myString, myIs2d, theTextAspect, (Standard_Integer )myExportHeight);
512 return;
2166f0fa 513 }
a174a3c5 514#endif
2166f0fa 515
a174a3c5 516 if (myVertsVbo.Length() == myTextures.Length())
2166f0fa 517 {
a174a3c5 518 for (Standard_Integer anIter = 0; anIter < myTextures.Length(); ++anIter)
519 {
520 const GLuint aTexId = myTextures.Value (anIter);
521 const Handle(OpenGl_VertexBuffer)& aVerts = myVertsVbo.Value (anIter);
522 const Handle(OpenGl_VertexBuffer)& aTCrds = myTCrdsVbo.Value (anIter);
523 aVerts->BindFixed (theCtx, GL_VERTEX_ARRAY);
524 aTCrds->BindFixed (theCtx, GL_TEXTURE_COORD_ARRAY);
525 glBindTexture (GL_TEXTURE_2D, aTexId);
526
527 glDrawArrays (GL_TRIANGLES, 0, GLsizei(aVerts->GetElemsNb()));
528
529 glBindTexture (GL_TEXTURE_2D, 0);
27583309 530 aTCrds->UnbindFixed (theCtx, GL_TEXTURE_COORD_ARRAY);
a174a3c5 531 aVerts->UnbindFixed (theCtx, GL_VERTEX_ARRAY);
532 }
2166f0fa 533 }
a174a3c5 534 else if (myVertsArray.Length() == myTextures.Length())
535 {
536 glEnableClientState (GL_VERTEX_ARRAY);
537 glEnableClientState (GL_TEXTURE_COORD_ARRAY);
538 for (Standard_Integer anIter = 0; anIter < myTextures.Length(); ++anIter)
539 {
540 const GLuint aTexId = myTextures.Value (anIter);
541 const Handle(OpenGl_Vec2Array)& aVerts = myVertsArray.Value (anIter);
542 const Handle(OpenGl_Vec2Array)& aTCrds = myTCrdsArray.Value (anIter);
543
544 glVertexPointer (2, GL_FLOAT, 0, (GLfloat* )&aVerts->First());
545 glTexCoordPointer (2, GL_FLOAT, 0, (GLfloat* )&aTCrds->First());
546 glBindTexture (GL_TEXTURE_2D, aTexId);
2166f0fa 547
a174a3c5 548 glDrawArrays (GL_TRIANGLES, 0, aVerts->Length());
2166f0fa 549
a174a3c5 550 glBindTexture (GL_TEXTURE_2D, 0);
551 }
552 glDisableClientState (GL_TEXTURE_COORD_ARRAY);
553 glDisableClientState (GL_VERTEX_ARRAY);
554 }
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;
603 glPushAttrib (GL_TEXTURE_BIT);
604 aFont = new OpenGl_Font (aFontFt, theKey);
605 if (!aFont->Init (aCtx))
606 {
607 //glPopAttrib();
608 //return aFont; // out of resources?
609 }
610 glPopAttrib(); // texture bit
611
612 aCtx->ShareResource (theKey, aFont);
613 }
614 return aFont;
615}
616
617// =======================================================================
618// function : render
619// purpose :
620// =======================================================================
621void OpenGl_Text::render (const Handle(OpenGl_PrinterContext)& thePrintCtx,
622 const Handle(OpenGl_Context)& theCtx,
623 const OpenGl_AspectText& theTextAspect,
624 const TEL_COLOUR& theColorText,
625 const TEL_COLOUR& theColorSubs) const
626{
627 if (myString.IsEmpty())
628 {
629 return;
630 }
631
632 const TCollection_AsciiString aFontKey = FontKey (theTextAspect, myParams.Height);
633 if (!myFont.IsNull()
634 && !myFont->ResourceKey().IsEqual (aFontKey))
635 {
636 // font changed
10b9c7df 637 const_cast<OpenGl_Text* > (this)->Release (theCtx.operator->());
a174a3c5 638 }
639
640 if (myFont.IsNull())
641 {
642 myFont = FindFont (theCtx, theTextAspect, myParams.Height, aFontKey);
643 if (myFont.IsNull())
644 {
645 return;
646 }
647 }
648
649 if (myTextures.IsEmpty())
650 {
651 OpenGl_TextFormatter aFormatter;
652 aFormatter.SetupAlignment (myParams.HAlign, myParams.VAlign);
653 aFormatter.Reset();
654 aFormatter.Append (theCtx, myString, *myFont.operator->());
655 aFormatter.Format();
656
58655684 657 if (!theCtx->caps->vboDisable && theCtx->core15 != NULL)
a174a3c5 658 {
659 aFormatter.Result (theCtx, myTextures, myVertsVbo, myTCrdsVbo);
660 }
661 else
662 {
663 aFormatter.Result (theCtx, myTextures, myVertsArray, myTCrdsArray);
664 }
665 aFormatter.BndBox (myBndBox);
666 }
667
668 if (myTextures.IsEmpty())
669 {
670 return;
671 }
672
673 myExportHeight = 1.0f;
674 myScaleHeight = 1.0f;
675
676 glMatrixMode (GL_MODELVIEW);
677 glPushMatrix();
678 if (!myIs2d)
679 {
680 // retrieve active matrices for project/unproject calls
681 glGetDoublev (GL_MODELVIEW_MATRIX, myModelMatrix);
682 glGetDoublev (GL_PROJECTION_MATRIX, myProjMatrix);
683 glGetIntegerv (GL_VIEWPORT, myViewport);
684 gluProject (myPoint.x(), myPoint.y(), myPoint.z(),
685 myModelMatrix, myProjMatrix, myViewport,
686 &myWinX, &myWinY, &myWinZ);
687
688 // compute scale factor for constant text height
689 GLdouble x1, y1, z1;
690 gluUnProject (myWinX, myWinY, myWinZ,
691 (GLdouble* )THE_IDENTITY_MATRIX, myProjMatrix, myViewport,
692 &x1, &y1, &z1);
693
694 GLdouble x2, y2, z2;
695 const GLdouble h = (GLdouble )myFont->FTFont()->PointSize();
353474f0 696 gluUnProject (myWinX, myWinY + h, myWinZ,
a174a3c5 697 (GLdouble* )THE_IDENTITY_MATRIX, myProjMatrix, myViewport,
698 &x2, &y2, &z2);
699
700 myScaleHeight = (y2 - y1) / h;
701 if (theTextAspect.IsZoomable())
702 {
703 myExportHeight = (float )h;
704 }
705 }
706 myExportHeight = (float )myFont->FTFont()->PointSize() / myExportHeight;
707
708 // push enabled flags to the stack
709 glPushAttrib (GL_ENABLE_BIT);
5322131b 710 glDisable (GL_LIGHTING);
a174a3c5 711
712 // setup depth test
713 if (!myIs2d
714 && theTextAspect.StyleType() != Aspect_TOST_ANNOTATION)
715 {
716 glEnable (GL_DEPTH_TEST);
717 }
718 else
719 {
720 glDisable (GL_DEPTH_TEST);
721 }
722
723 // setup alpha test
724 GLint aTexEnvParam = GL_REPLACE;
725 glGetTexEnviv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &aTexEnvParam);
726 if (aTexEnvParam != GL_REPLACE)
727 {
728 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
729 }
730 glAlphaFunc (GL_GEQUAL, 0.285f);
731 glEnable (GL_ALPHA_TEST);
732
733 // setup blending
734 glEnable (GL_BLEND);
735 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE
736
737 // activate texture unit
738 glDisable (GL_TEXTURE_1D);
739 glEnable (GL_TEXTURE_2D);
01ca42b2 740 if (theCtx->core15fwd != NULL)
a174a3c5 741 {
01ca42b2 742 theCtx->core15fwd->glActiveTexture (GL_TEXTURE0);
a174a3c5 743 }
744
745 // extra drawings
746 switch (theTextAspect.DisplayType())
747 {
2166f0fa 748 case Aspect_TODT_BLEND:
a174a3c5 749 {
750 glEnable (GL_COLOR_LOGIC_OP);
751 glLogicOp (GL_XOR);
2166f0fa 752 break;
a174a3c5 753 }
2166f0fa
SK
754 case Aspect_TODT_SUBTITLE:
755 {
a174a3c5 756 glColor3fv (theColorSubs.rgb);
757 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (0.0f, 0.0f, 0.00001f));
758
759 glBindTexture (GL_TEXTURE_2D, 0);
760 glBegin (GL_QUADS);
761 glVertex2f (myBndBox.Left, myBndBox.Top);
762 glVertex2f (myBndBox.Right, myBndBox.Top);
763 glVertex2f (myBndBox.Right, myBndBox.Bottom);
764 glVertex2f (myBndBox.Left, myBndBox.Bottom);
2166f0fa
SK
765 glEnd();
766 break;
767 }
2166f0fa 768 case Aspect_TODT_DEKALE:
a174a3c5 769 {
770 glColor3fv (theColorSubs.rgb);
771 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (+1.0f, +1.0f, 0.00001f));
772 drawText (thePrintCtx, theCtx, theTextAspect);
773 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (-1.0f, -1.0f, 0.00001f));
774 drawText (thePrintCtx, theCtx, theTextAspect);
775 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (-1.0f, +1.0f, 0.00001f));
776 drawText (thePrintCtx, theCtx, theTextAspect);
777 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (+1.0f, -1.0f, 0.00001f));
778 drawText (thePrintCtx, theCtx, theTextAspect);
779 break;
780 }
a6eb515f 781 case Aspect_TODT_DIMENSION:
a174a3c5 782 case Aspect_TODT_NORMAL:
783 {
2166f0fa
SK
784 break;
785 }
786 }
787
a174a3c5 788 // main draw call
789 glColor3fv (theColorText.rgb);
790 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (0.0f, 0.0f, 0.0f));
791 drawText (thePrintCtx, theCtx, theTextAspect);
2166f0fa 792
a174a3c5 793 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, aTexEnvParam);
543f0db0 794
795 if (theTextAspect.DisplayType() == Aspect_TODT_DIMENSION)
796 {
797 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (0.0f, 0.0f, 0.00001f));
798
799 glDisable (GL_BLEND);
800 glDisable (GL_TEXTURE_2D);
801 glDisable (GL_ALPHA_TEST);
802 if (!myIs2d)
803 {
804 glDisable (GL_DEPTH_TEST);
805 }
806 glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
807
808 glClear (GL_STENCIL_BUFFER_BIT);
809 glEnable (GL_STENCIL_TEST);
810 glStencilFunc (GL_ALWAYS, 1, 0xFF);
811 glStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE);
812
813 glBegin (GL_QUADS);
814 glVertex2f (myBndBox.Left, myBndBox.Top);
815 glVertex2f (myBndBox.Right, myBndBox.Top);
816 glVertex2f (myBndBox.Right, myBndBox.Bottom);
817 glVertex2f (myBndBox.Left, myBndBox.Bottom);
818 glEnd();
819
820 glStencilFunc (GL_ALWAYS, 0, 0xFF);
821 // glPopAttrib() will reset state for us
822 //glDisable (GL_STENCIL_TEST);
823 //if (!myIs2d) glEnable (GL_DEPTH_TEST);
824
825 glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
826 }
827
828 // revert OpenGL state
a174a3c5 829 glPopAttrib(); // enable bit
830 glPopMatrix(); // model view matrix was modified
5e27df78 831}