Merging OCC22105, OCC22354, OCC22150 , OCC22199 , OCC22391 and OCC22108
[occt.git] / src / OpenGl / OpenGl_TextRender.cxx
1 /*
2 * Includes
3 */
4 #include <stdio.h>
5 #include <string.h>
6
7 #include <TCollection_AsciiString.hxx>
8 #include <TCollection_HAsciiString.hxx>
9
10 #include <Standard_Stream.hxx>
11
12 #include <OpenGl_FontMgr.hxx>   
13 #include <OpenGl_tgl_funcs.hxx>
14 #include <OpenGl_TextRender.hxx>
15 #include <OpenGl_telem_attri.hxx>
16 #include <OpenGl_cmn_varargs.hxx>
17
18 #include <OSD_Environment.hxx>
19 #include <Quantity_NameOfColor.hxx>
20 #include <AlienImage.hxx>
21
22 #ifdef HAVE_GL2PS
23 #include <gl2ps.h>
24 #endif
25
26
27 /*-----------------------------------------------------------------------------*/
28 /*
29 * Prototypes variables statiques
30 */                                                 
31
32 int OpenGl_TextRender::curFont    = -1;
33 int OpenGl_TextRender::curSize    = -1;
34 int OpenGl_TextRender::curScale   = -1;
35 int OpenGl_TextRender::curTexFont = -1;
36
37 OpenGl_TextRender::FontMapNode OpenGl_TextRender::fontMap[] = {
38
39 #ifdef WNT
40
41   { "Courier"                  , "Courier New"    , OSD_FA_Regular },
42   { "Times-Roman"              , "Times New Roman", OSD_FA_Regular  },
43   { "Times-Bold"               , "Times New Roman", OSD_FA_Bold },
44   { "Times-Italic"             , "Times New Roman", OSD_FA_Italic  },
45   { "Times-BoldItalic"         , "Times New Roman", OSD_FA_BoldItalic  },
46   { "ZapfChancery-MediumItalic", "Script"         , OSD_FA_Regular  },
47   { "Symbol"                   , "Symbol"         , OSD_FA_Regular  },
48   { "ZapfDingbats"             , "WingDings"      , OSD_FA_Regular  },
49   { "Rock"                     , "Arial"          , OSD_FA_Regular  },
50   { "Iris"                     , "Lucida Console" , OSD_FA_Regular  }
51
52 #else   //X11
53
54   { "Courier"                  , "Courier"      , OSD_FA_Regular },
55   { "Times-Roman"              , "Times"        , OSD_FA_Regular  },
56   { "Times-Bold"               , "Times"        , OSD_FA_Bold },
57   { "Times-Italic"             , "Times"        , OSD_FA_Italic  },
58   { "Times-BoldItalic"         , "Times"        , OSD_FA_BoldItalic  },
59   { "Arial"                    , "Helvetica"    , OSD_FA_Regular  }, 
60   { "ZapfChancery-MediumItalic", "-adobe-itc zapf chancery-medium-i-normal--*-*-*-*-*-*-iso8859-1"              , OSD_FA_Regular  },
61   { "Symbol"                   , "-adobe-symbol-medium-r-normal--*-*-*-*-*-*-adobe-fontspecific"                , OSD_FA_Regular  },
62   { "ZapfDingbats"             , "-adobe-itc zapf dingbats-medium-r-normal--*-*-*-*-*-*-adobe-fontspecific"     , OSD_FA_Regular  },
63   { "Rock"                     , "-sgi-rock-medium-r-normal--*-*-*-*-p-*-iso8859-1"                             , OSD_FA_Regular  },
64   { "Iris"                     , "--iris-medium-r-normal--*-*-*-*-m-*-iso8859-1"                                , OSD_FA_Regular  }
65 #endif
66
67 };  
68
69 OpenGl_TextRender::FontEntry OpenGl_TextRender::fontEntry[] = {
70
71   { "Courier"                  , "Courier New"                 },
72   { "Times-Roman"              , "Times New Roman"             },
73   { "Times-Bold"               , "Times New Roman Bold"        },
74   { "Times-Italic"             , "Times New Roman Italic"      },
75   { "Times-BoldItalic"         , "Times New Roman Bold Italic" },
76   { "ZapfChancery-MediumItalic", "Script"                      },
77   { "Symbol"                   , "Symbol"                      },
78   { "ZapfDingbats"             , "WingDings"                   },
79   { "Rock"                     , "Arial"                       },
80   { "Iris"                     , "Lucida Console"              }
81
82 };
83
84 #define NUM_FONT_ENTRIES (sizeof(fontMap)/sizeof(FontMapNode))
85
86 /*-----------------------------------------------------------------------------*/
87
88 /*
89 *  Constants
90 */
91
92 #ifdef HAVE_GL2PS
93 void OpenGl_TextRender::getGL2PSFontName(char *src_font, char *ps_font)
94 {
95   /* 
96   Convert font name used for rendering to some "good" font names
97   that produce good vector text 
98   */
99   static char const *family[] = {"Helvetica", "Courier", "Times"};
100   static char const *italic[] = {"Oblique", "Oblique", "Italic"};
101   static char const *base[] = {"", "", "-Roman"};
102
103   int font = 0;
104   int isBold = 0;
105   int isItalic = 0;
106
107
108   if( strstr( src_font, "Symbol" ) ){
109     sprintf( ps_font, "%s", "Symbol" );
110     return;
111   }
112
113   if( strstr( src_font, "ZapfDingbats" ) ){
114     sprintf( ps_font, "%s", "WingDings" );
115     return;
116   }
117
118   if ( strstr( src_font, "Courier" ) ){
119     font = 1;
120   }
121   else if ( strstr( src_font, "Times" ) ){
122     font = 2;
123   }
124
125   if ( strstr( src_font, "Bold" ) ){
126     isBold = 1;
127   }
128
129   if ( strstr( src_font, "Italic" ) || strstr( src_font, "Oblique" ) ){
130     isItalic = 1;
131   }
132
133   if ( isBold ){
134     sprintf( ps_font, "%s-%s", family[font], "Bold");
135     if ( isItalic ){
136       sprintf(ps_font, "%s%s", ps_font, italic[font]);
137     }
138   }
139   else if ( isItalic )
140   {
141     sprintf( ps_font, "%s-%s", family[font], italic[font] );
142   }
143   else
144   {
145     sprintf( ps_font, "%s%s", family[font], base[font] );
146   }
147 }
148 #endif
149
150 /*-----------------------------------------------------------------------------*/
151
152 /*
153 * Constructors
154 */
155
156 OpenGl_TextRender::OpenGl_TextRender()
157 : _CurrentFontId(-1),
158 _XCurrentScale(1.f),
159 _YCurrentScale(1.f) {
160 }
161
162
163
164 /*-----------------------------------------------------------------------------*/
165
166 /*
167 * Fonctions publiques 
168 */
169
170 OpenGl_TextRender* OpenGl_TextRender::instance() {
171   static OpenGl_TextRender* _textRend = NULL;
172   if ( _textRend == NULL )
173   {
174     _textRend = new OpenGl_TextRender();
175   }
176
177   return _textRend;
178 }
179
180
181 /*----------------------------------------------------------------------*/
182 OpenGl_TextRender::FontMapNode OpenGl_TextRender::searchFontInMap( Handle(TCollection_HAsciiString)& fontName ) {
183   for ( int i = 0; i < NUM_FONT_ENTRIES; ++i )
184   {
185     TCollection_AsciiString compare_String(fontMap[i].enumName) ;
186     if(compare_String.IsEqual( fontName->ToCString() ))
187     {
188       return fontMap[i];
189     }  
190   }   
191   //default font returns
192   return fontMap[0];
193 }
194
195 /*-----------------------------------------------------------------------------*/
196
197 Tint OpenGl_TextRender::FindFont ( Tchar* fontName,
198                                   OSD_FontAspect aspect,
199                                   Tfloat bestSize,
200                                   Tfloat xScale ,
201                                   Tfloat yScale ) 
202 {   
203   if (!fontName)
204     return -1;
205   OpenGl_FontMgr* mgr =  OpenGl_FontMgr::instance();  
206
207   Handle(TCollection_HAsciiString) family_name
208     = new TCollection_HAsciiString((char*)fontName);
209
210   curFont = mgr->request_font(family_name,
211     aspect,
212     Standard_Integer(bestSize) );
213
214   if( curFont == -1 ) {
215     //try to use font names mapping
216     FontMapNode newTempFont = searchFontInMap ( family_name );
217     curFont = mgr->request_font( new TCollection_HAsciiString(newTempFont.FontName),
218       newTempFont.fontAspect,
219       Standard_Integer(bestSize) );
220   }
221
222   // Requested family name not found -> serach for any font family with given aspect and height
223   family_name = new TCollection_HAsciiString( "" );
224   if ( curFont == -1 ) {
225     curFont = mgr->request_font(family_name, aspect, Standard_Integer(bestSize) );
226   }
227
228   // The last resort: trying to use ANY font available in the system
229   if ( curFont == -1 ) {
230     curFont = mgr->request_font(family_name, OSD_FA_Undefined, -1 );
231   }
232
233   if ( curFont != -1 )
234     mgr->setCurrentScale( xScale, yScale );
235   return curFont;
236
237 }
238
239 /*-----------------------------------------------------------------------------*/
240 void OpenGl_TextRender::StringSize(char *str, GLint *Width, GLint *Ascent, GLint *Descent)
241 {
242
243   /*    int       dir, asc, des;*/
244   *Ascent = 0;
245   *Descent = 0;
246   *Width = 0;
247   if (curFont != -1) {
248     OpenGl_FontMgr* mgr = OpenGl_FontMgr::instance();
249     const FTFont* font = mgr->fontById( curFont );
250     if ( font ) {
251       *Width = GLint( mgr->computeWidth( curFont, str ) );
252       *Ascent = GLint( font->Ascender() );
253       *Descent = GLint( font->Descender() );
254     }
255   }
256 #ifdef TRACE
257   printf("sizeString::asc = %d des = %d width = %d \n", *Ascent, *Descent, *Width); 
258 #endif
259
260 }
261
262 /*-----------------------------------------------------------------------------*/
263
264 void OpenGl_TextRender::RenderText ( char* str, GLuint base, int is2d, GLfloat x, GLfloat y, GLfloat z ) 
265 {
266   GLdouble projMatrix[4][4], modelMatrix[4][4];
267   GLint viewport[4];
268   GLint widthFont, ascentFont, descentFont;
269   GLdouble xdis = 0., ydis = 0.;
270   GLint renderMode;  
271
272   // FTFont changes texture state when it renders and computes size for the text
273   glPushAttrib(GL_TEXTURE_BIT);
274   StringSize(str, &widthFont, &ascentFont, &descentFont );
275
276   GLdouble identityMatrix[4][4] = 
277   {
278     {1.,0.,0.,0.},
279     {0.,1.,0.,0.},
280     {0.,0.,1.,0.},
281     {0.,0.,0.,1.}
282   };
283
284   TEL_ALIGN_DATA align;
285
286   CMN_KEY key;
287   key.id = TelTextAlign;
288   key.data.pdata = &align;
289   TsmGetAttri( 1, &key );
290
291   Tfloat angle = 0;
292   CMN_KEY keyAngle;
293   keyAngle.id = TelTextAngle;//This flag responding about Angle text
294   TsmGetAttri( 1, &keyAngle );
295   angle = keyAngle.data.ldata;
296
297   Tint zoom = 0;
298   CMN_KEY keyZoom;
299   keyZoom.id = TelTextZoomable;//This flag responding about Zoomable text
300   TsmGetAttri( 1, &keyZoom );
301   zoom = keyZoom.data.ldata;
302
303   OpenGl_TextRender* textRender = OpenGl_TextRender::instance(); 
304   int vh = 2 ;
305   int vv = 2 ;
306
307   switch( align.Hmode )
308   {
309   case CALL_PHIGS_HOR_LEFT://0
310     xdis =0.; vh = 1;
311     break;
312   case CALL_PHIGS_HOR_CENTER://1
313     xdis = -(GLdouble)widthFont / 2.0;  vh = 2;
314     break;
315   case CALL_PHIGS_HOR_RIGHT://2
316     xdis = -(GLdouble)widthFont; vh = 3;
317     break;
318   default:
319     xdis = 0.;
320   }
321
322   switch( align.Vmode )
323   {
324   case CALL_PHIGS_VERT_BOTTOM://0
325     ydis = 0.; vv = 1;
326     break;
327   case CALL_PHIGS_VERT_CENTER://1
328     ydis = -(GLdouble)(ascentFont) / 2.0 - descentFont; vv = 2;
329     break;
330   case CALL_PHIGS_VERT_TOP://2
331     ydis = -(GLdouble)ascentFont - descentFont; vv= 3;
332     break;    
333   default:
334     ydis = 0.;
335   }
336
337   OpenGl_FontMgr* mgr = OpenGl_FontMgr::instance();
338
339   const FTFont* fnt = mgr->fontById( curFont );
340   if ( !fnt ) {
341     glPopAttrib();
342     return; 
343   }
344
345   float export_h = 1.;
346
347   glMatrixMode(GL_MODELVIEW);
348   glPushMatrix();
349   if (is2d) {
350     glLoadIdentity();
351     glTranslatef(x, y, 0.f);
352     glRotatef( 180, 1, 0, 0 );
353   }
354   else {   
355     GLdouble wx, wy, wz;
356     GLdouble x1, y1, z1;
357     GLdouble x2, y2, z2;
358
359     glGetDoublev( GL_MODELVIEW_MATRIX, (GLdouble*)modelMatrix );
360     glGetDoublev( GL_PROJECTION_MATRIX, (GLdouble*)projMatrix );
361     glGetIntegerv( GL_VIEWPORT, (GLint*)viewport );
362
363     gluProject( x, y, z,
364       (GLdouble*)modelMatrix,
365       (GLdouble*)projMatrix,
366       (GLint*)viewport,
367       &wx, &wy, &wz );
368     glLoadIdentity();
369     gluUnProject( wx, wy, wz, 
370       (GLdouble*)identityMatrix, (GLdouble*)projMatrix, (GLint*)viewport,
371       &x1, &y1 , &z1 );    
372
373     GLdouble h = (GLdouble)fnt->FaceSize();
374
375
376     gluUnProject( wx, wy + h - 1., wz,
377       (GLdouble*)identityMatrix, (GLdouble*)projMatrix, (GLint*)viewport,
378       &x2, &y2, &z2 );
379
380     h = (y2-y1)/h;
381
382     glTranslated( x1, y1 , z1 );   
383     glRotated(angle, 0, 0, 1); 
384     glTranslated(xdis, ydis, 0);  
385
386     if( ! zoom )
387     {
388       glScaled( h, h, h );
389     }
390     else
391     {
392       export_h = h;
393     }
394   }
395   glGetIntegerv(GL_RENDER_MODE, &renderMode);
396   if ( renderMode == GL_FEEDBACK ) 
397   {
398 #ifdef HAVE_GL2PS
399     CMN_KEY keyfontName;
400     keyfontName.id = TelTextFont;//This flag responding about TextFontName
401     TsmGetAttri( 1, &keyfontName );
402     char *fontName = new char[strlen((char*)keyfontName.data.pdata) + 1];
403     strcpy(fontName,(char*)keyfontName.data.pdata);
404
405     export_h = (GLdouble)fnt->FaceSize() / export_h;
406     int aligment = alignmentforgl2ps( vh, vv );
407     glPopMatrix();
408     ExportText( str, fontName, export_h, angle, aligment, x, y, z, is2d!=0 );
409     delete [] fontName;
410 #endif
411   }
412   else
413   {
414     mgr->render_text( curFont, str, is2d );
415     glPopMatrix();
416   }
417   glPopAttrib();
418   return;
419
420 }
421
422 #ifdef HAVE_GL2PS
423 int OpenGl_TextRender::alignmentforgl2ps(int vh, int vy)
424 {
425   if( vh == 1 && vy == 1)
426   {
427     return 5;
428   }
429   if( vh == 2 && vy == 1)
430   {
431     return 4;
432   }
433   if( vh == 3 && vy == 1)
434   {
435     return 6;
436   }
437
438   if( vh == 1 && vy == 2)
439   {
440     return 2;
441   }
442   if( vh == 2 && vy == 2)
443   {
444     return 1;
445   }
446   if( vh == 3 && vy == 2)
447   {
448     return 3;
449   }
450
451   if( vh == 1 && vy == 3)
452   {
453     return 8;
454   }
455   if( vh == 2 && vy == 3)
456   {
457     return 7;
458   }
459   if( vh == 3 && vy == 3)
460   {
461     return 9;
462   }
463   return 0;
464 };
465 #endif
466
467 /*-----------------------------------------------------------------------------*/
468 void OpenGl_TextRender::ExportText( char* str, char* fontname, GLfloat height, GLfloat angle, GLint alignment,
469                                     GLfloat x, GLfloat y, GLfloat z, GLboolean is2d )
470 {
471 #ifdef HAVE_GL2PS
472
473   GLubyte zero = 0;
474   char ps_font[64];
475
476   getGL2PSFontName(fontname, ps_font);
477
478   if( is2d )
479     glRasterPos2f( x, y );
480   else
481     glRasterPos3f( x, y, z );
482   
483   glBitmap( 1, 1, 0, 0, 0, 0, &zero );
484
485   gl2psTextOpt( str, ps_font, height, alignment, angle);
486
487 #endif
488
489 }