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