Merging OCC22105, OCC22354, OCC22150 , OCC22199 , OCC22391 and OCC22108
[occt.git] / src / OpenGl / OpenGl_text.cxx
1 /***********************************************************************
2
3 FONCTION :
4 ----------
5 File OpenGl_text :
6
7
8 REMARQUES:
9 ---------- 
10
11
12 HISTORIQUE DES MODIFICATIONS   :
13 --------------------------------
14 xx-xx-xx : xxx ; Creation.
15 05-03-96 : FMN ; Suppression code inutile:
16 01-04-96 : CAL ; Integration MINSK portage WNT
17 29-04-96 : FMN ; correction warning de compilation.
18 21-10-96 : FMN ; Suppression LMC_COLOR fait dans OpenGl_execstruct.c
19 30-11-98 : FMN ; S4069 : Textes toujours visibles
20 02.14.100 : JR : Warnings on WNT truncations from double to float
21 21.06.03 : SAN : Suppress text display while in animation mode (TEXT_DEGENER)
22 22.01.04 : SAN : Implement texture mapped fonts on WNT only (OCC2934)
23
24 ************************************************************************/
25
26 /*----------------------------------------------------------------------*/
27 /*
28 * Includes
29 */ 
30
31 #ifndef WNT
32 #include <X11/Xlib.h>
33 #endif
34 #include <OpenGl_tgl_all.hxx>
35
36 #include <stddef.h>
37 #include <string.h>
38 #include <stdio.h>
39 #include <GL/gl.h>
40 #include <GL/glu.h>
41
42 #include <OpenGl_cmn_varargs.hxx>
43 #include <OpenGl_telem_attri.hxx>
44 #include <OpenGl_tsm.hxx>
45 #include <OpenGl_telem.hxx>
46 #include <OpenGl_telem_highlight.hxx>
47 #include <OpenGl_telem_inquire.hxx>
48 #include <OpenGl_tgl_funcs.hxx>
49 #include <OpenGl_Extension.hxx>
50 #include <OpenGl_Memory.hxx>
51
52
53 #include <OpenGl_TextRender.hxx>
54
55 /*----------------------------------------------------------------------*/
56 /*
57 * Fonctions statiques
58 */
59
60 static  TStatus  TextDisplay( TSM_ELEM_DATA, Tint, cmn_key* );
61 static  TStatus  TextAdd( TSM_ELEM_DATA, Tint, cmn_key* );
62 static  TStatus  TextDelete( TSM_ELEM_DATA, Tint, cmn_key* );
63 static  TStatus  TextPrint( TSM_ELEM_DATA, Tint, cmn_key* );
64 static  TStatus  TextInquire( TSM_ELEM_DATA, Tint, cmn_key* );
65
66 #if defined(__sun) || defined (__osf__) || defined (__hp) || defined (__sgi) 
67 #else
68 PFNGLBLENDEQUATIONEXTPROC glBlendEquationOp = (PFNGLBLENDEQUATIONEXTPROC) INVALID_EXT_FUNCTION_PTR;
69 #endif
70 /*----------------------------------------------------------------------*/
71 /*
72 * Constantes 
73 */
74
75 #if defined(__osf__) || defined (__sun) || defined (__sgi) || defined(__hp9000s700) || defined(WNT)
76 #undef GL_EXT_blend_logic_op
77 #endif
78
79 /*----------------------------------------------------------------------*/
80 /*
81 * Variables statiques
82 */
83
84 /*static GLboolean lighting_mode;*/
85
86 static  TStatus  (*MtdTbl[])( TSM_ELEM_DATA, Tint, cmn_key* ) =
87 {
88   TextDisplay,
89   TextDisplay,
90   TextAdd,
91   TextDelete,
92   TextPrint,
93   TextInquire
94 };
95
96 extern GLuint fontBase;
97 extern GLuint printerFontBase;
98
99 #define TEXT_DEGENER
100
101 #ifdef TEXT_DEGENER
102 extern int    g_nDegenerateModel;
103 extern float  g_fSkipRatio;
104 #endif
105
106 void putText( Tchar* data, Tfloat x, Tfloat y, Tfloat z )
107 {
108   OpenGl_TextRender* textRender=OpenGl_TextRender::instance();
109   textRender->RenderText ( (char*)data, fontBase, 0, x, y, z );
110 }
111
112 /*----------------------------------------------------------------------*/
113
114 MtblPtr
115 TelTextInitClass( TelType* el )
116 {
117   *el = TelText;
118   return MtdTbl;
119 }
120
121 /*----------------------------------------------------------------------*/
122
123 static  TStatus
124 TextAdd( TSM_ELEM_DATA d, Tint n, cmn_key *k )
125 {
126   Tint           i;
127   TEL_POINT      def_pt = {{ ( float )0.0, ( float )0.0, ( float )0.0 }};
128   tel_point      pt = &def_pt;
129   tel_text_data  data;
130   Tchar          *str= 0;
131
132   for( i = 0; i < n; i++ )
133   {
134     switch( k[i]->id )
135     {
136     case TEXT_ATTACH_PT_ID:
137       pt = (tel_point)k[i]->data.pdata;
138       break;
139     case TEXT_STRING_ID:
140       str = (Tchar*)k[i]->data.pdata;
141       break;
142     }
143   }
144
145   i = strlen((char*)str) + 1;
146
147   data = new TEL_TEXT_DATA();
148   if( !data )
149     return TFailure;
150   data->data = new Tchar[i];
151   if( !data->data )
152     return TFailure;
153
154   data->attach_pt = *pt;
155   data->length    = i;
156   memcpy( data->data, str, i );
157
158   ((tsm_elem_data)(d.pdata))->pdata = data;
159
160   return TSuccess;
161 }
162
163 /*----------------------------------------------------------------------*/
164
165 static  TStatus
166 TextDisplay( TSM_ELEM_DATA data, Tint n, cmn_key *k )
167 {
168   tel_text_data   d;
169   CMN_KEY         key, key1;
170   TEL_COLOUR      colour,  colours;
171   int             style,  display_type;
172   GLboolean       flag_zbuffer = GL_FALSE;
173   GLboolean       blend_state = GL_FALSE; 
174   GLint           sWidth, sAscent, sDescent;
175   GLdouble        modelMatrix[16], projMatrix[16];
176   GLint           viewport[4];
177   GLdouble        objrefX, objrefY, objrefZ;
178   GLdouble        objX, objY, objZ;
179   GLdouble        obj1X, obj1Y, obj1Z;
180   GLdouble        obj2X, obj2Y, obj2Z;
181   GLdouble        obj3X, obj3Y, obj3Z;
182   GLdouble        winx1, winy1, winz1;
183   GLdouble        winx, winy, winz;
184   GLint           status;
185
186 #ifdef TEXT_DEGENER
187   if ( g_nDegenerateModel > 0 && g_fSkipRatio == 1. )
188     return TSuccess;
189 #endif
190
191   d = (tel_text_data)data.pdata;
192
193   if( k[0]->id == TOn )
194   {                           /* Use highlight colours */
195     TEL_HIGHLIGHT  hrep;
196
197     key.id = TelHighlightIndex;
198     TsmGetAttri( 1, &key );
199     if( TelGetHighlightRep( TglActiveWs, key.data.ldata, &hrep )
200       == TSuccess )
201       colour = hrep.col;
202     else
203     {
204       TelGetHighlightRep( TglActiveWs, 0, &hrep );
205       colour = hrep.col;
206     }
207   }
208   else
209   {
210     key.id = TelTextColour;
211     key.data.pdata = &colour;
212     TsmGetAttri( 1, &key );
213   }
214
215   key.id = TelTextStyle;
216   key1.id = TelTextDisplayType;
217   TsmGetAttri( 2, &key, &key1 );
218   style = key.data.ldata;
219   display_type = key1.data.ldata;
220
221   /* style annotation */
222   if (style == ASPECT_TOST_ANNOTATION)
223   {
224     flag_zbuffer = glIsEnabled(GL_DEPTH_TEST);
225     if (flag_zbuffer) glDisable(GL_DEPTH_TEST);
226   }
227
228   /* display type of text */
229   if (display_type != ASPECT_TODT_NORMAL)
230   {
231     key.id = TelTextColourSubTitle;
232     key.data.pdata = &colours;
233     TsmGetAttri( 1, &key );
234
235     /* Optimisation: il faudrait ne faire le Get qu'une fois par Redraw */
236     glGetIntegerv (GL_VIEWPORT, viewport);
237     glGetDoublev (GL_MODELVIEW_MATRIX, modelMatrix);
238     glGetDoublev (GL_PROJECTION_MATRIX, projMatrix);
239
240     OpenGl_TextRender* textRender=OpenGl_TextRender::instance();
241     switch (display_type) 
242     {
243     case ASPECT_TODT_BLEND:            
244
245 #if defined(GL_EXT_blend_logic_op)   
246       if ( (PFNGLBLENDEQUATIONEXTPROC)glBlendEquationOp == (PFNGLBLENDEQUATIONEXTPROC)INVALID_EXT_FUNCTION_PTR )
247       {
248         if(QueryExtension("GL_EXT_blend_logic_op")) {  
249 #ifdef WNT
250           glBlendEquationOp = (PFNGLBLENDEQUATIONEXTPROC)wglGetProcAddress("glBlendEquationOp");
251 #else
252           glBlendEquationOp = (PFNGLBLENDEQUATIONEXTPROC)glXGetProcAddress((GLubyte*)"glBlendEquationOp");
253 #endif  
254         } else
255           glBlendEquationOp = NULL;
256       }
257
258       if ( glBlendEquationOp )
259       {
260         blend_state = glIsEnabled(GL_BLEND);
261         if (!blend_state) glEnable(GL_BLEND);
262         glBlendEquationOp(GL_LOGIC_OP);
263         glLogicOp(GL_XOR); 
264       }
265 #else
266
267       blend_state = glIsEnabled(GL_BLEND);
268       if (!blend_state) glEnable(GL_BLEND);
269       glEnable(GL_COLOR_LOGIC_OP);
270       glLogicOp(GL_XOR); 
271
272 #endif
273       break;
274     case ASPECT_TODT_SUBTITLE:
275       textRender->StringSize((char *)d->data, &sWidth, &sAscent, &sDescent);
276       objrefX = (float)d->attach_pt.xyz[0];   
277       objrefY = (float)d->attach_pt.xyz[1];   
278       objrefZ = (float)d->attach_pt.xyz[2];
279       status = gluProject (objrefX, objrefY, objrefZ, modelMatrix, projMatrix, viewport,
280         &winx1, &winy1, &winz1);
281
282       winx = winx1;
283       winy = winy1-sDescent;
284       winz = winz1+0.00001;     
285       status = gluUnProject (winx, winy, winz, modelMatrix, projMatrix, viewport,
286         &objX, &objY, &objZ);
287
288       winx = winx1 + sWidth;
289       winy = winy1-sDescent;
290       winz = winz1+0.00001; /* il vaut mieux F+B / 1000000 ? */     
291       status = gluUnProject (winx, winy, winz, modelMatrix, projMatrix, viewport,
292         &obj1X, &obj1Y, &obj1Z);
293
294       winx = winx1 + sWidth;
295       winy = winy1 + sAscent;
296       winz = winz1+0.00001;     
297       status = gluUnProject (winx, winy, winz, modelMatrix, projMatrix, viewport,
298         &obj2X, &obj2Y, &obj2Z);
299
300       winx = winx1;
301       winy = winy1+ sAscent;
302       winz = winz1+0.00001;   
303       status = gluUnProject (winx, winy, winz, modelMatrix, projMatrix, viewport,
304         &obj3X, &obj3Y, &obj3Z);
305
306       glColor3fv( colours.rgb );
307       glBegin(GL_POLYGON);
308       glVertex3d(objX, objY, objZ);
309       glVertex3d(obj1X, obj1Y, obj1Z);
310       glVertex3d(obj2X, obj2Y, obj2Z);
311       glVertex3d(obj3X, obj3Y, obj3Z);
312       glEnd();
313       break;
314
315     case ASPECT_TODT_DEKALE:
316       objrefX = (float)d->attach_pt.xyz[0];   
317       objrefY = (float)d->attach_pt.xyz[1];   
318       objrefZ = (float)d->attach_pt.xyz[2];
319       status = gluProject (objrefX, objrefY, objrefZ, modelMatrix, projMatrix, viewport,
320         &winx1, &winy1, &winz1);
321
322       winx = winx1+1;
323       winy = winy1+1;
324       winz = winz1+0.00001;     
325       status = gluUnProject (winx, winy, winz, modelMatrix, projMatrix, viewport,
326         &objX, &objY, &objZ);
327
328       glColor3fv( colours.rgb );
329       putText( d->data, (float)objX, (float)objY,(float)objZ );
330       winx = winx1-1;
331       winy = winy1-1;
332       status = gluUnProject (winx, winy, winz, modelMatrix, projMatrix, viewport,
333         &objX, &objY, &objZ);
334
335       putText( d->data, (float)objX, (float)objY,(float)objZ );
336       winx = winx1-1;
337       winy = winy1+1;
338       status = gluUnProject (winx, winy, winz, modelMatrix, projMatrix, viewport,
339         &objX, &objY, &objZ); 
340
341       putText( d->data, (float)objX, (float)objY,(float)objZ );
342       winx = winx1+1;
343       winy = winy1-1;
344       status = gluUnProject (winx, winy, winz, modelMatrix, projMatrix, viewport,
345         &objX, &objY, &objZ);
346       putText( d->data, (float)objX, (float)objY,(float)objZ );
347       break;
348     }
349   }
350
351   glColor3fv( colour.rgb );
352   putText( d->data, (float)d->attach_pt.xyz[0], (float)d->attach_pt.xyz[1],(float)d->attach_pt.xyz[2] );
353   /* maj attributs */   
354   if (flag_zbuffer) glEnable(GL_DEPTH_TEST); 
355   if (display_type == ASPECT_TODT_BLEND) 
356   {
357 #if defined(GL_EXT_blend_logic_op) 
358     if ((!blend_state) && (QueryExtension("GL_EXT_blend_logic_op"))) glDisable(GL_BLEND);
359 #else
360     if (!blend_state) glDisable(GL_BLEND);
361     glDisable(GL_COLOR_LOGIC_OP);
362 #endif
363   }
364
365   return TSuccess;
366 }
367
368 /*----------------------------------------------------------------------*/
369
370 static  TStatus
371 TextDelete( TSM_ELEM_DATA data, Tint n, cmn_key *k )
372 {
373   if (data.pdata)
374     delete data.pdata;
375   return TSuccess;
376 }
377
378 /*----------------------------------------------------------------------*/
379
380 static  TStatus
381 TextPrint( TSM_ELEM_DATA data, Tint n, cmn_key *k )
382 {
383   tel_text_data p;
384
385   p = (tel_text_data)data.pdata;
386
387   fprintf( stdout, "TelText.\n" );
388   fprintf( stdout, "\t\tString : %s\n", p->data );
389   fprintf( stdout, "\t\tAttach Point : %f %f %f\n", p->attach_pt.xyz[0],
390     p->attach_pt.xyz[1],
391     p->attach_pt.xyz[2] );
392   fprintf( stdout, "\n" );
393
394   return TSuccess;
395 }
396
397 /*----------------------------------------------------------------------*/
398
399 static TStatus
400 TextInquire( TSM_ELEM_DATA data, Tint n, cmn_key *k )
401 {
402   Tint          i;
403   tel_text_data d;
404   Tint          size_reqd=0;
405   TStatus       status = TSuccess;
406
407   d = (tel_text_data)data.pdata;
408
409   size_reqd = d->length;
410
411   for( i = 0; i < n; i++ )
412   {
413     switch( k[i]->id )
414     {
415     case INQ_GET_SIZE_ID:
416       {
417         k[i]->data.ldata = size_reqd;
418         break;
419       }
420
421     case INQ_GET_CONTENT_ID:
422       {
423         TEL_INQ_CONTENT *c;
424         Teldata         *w;
425
426         c = (tel_inq_content)k[i]->data.pdata;
427         c->act_size = size_reqd;
428         w = c->data;
429
430         if( c->size >= size_reqd )
431         {
432           w->atext3.string = c->buf;
433           w->atext3.ref_pt = d->attach_pt;
434           w->atext3.anno.xyz[0] = ( float )0.0;
435           w->atext3.anno.xyz[1] = ( float )0.0;
436           w->atext3.anno.xyz[2] = ( float )0.0;
437           strcpy( (char*)w->atext3.string, (char*)d->data );
438           status = TSuccess;
439         }
440         else
441           status = TFailure;
442         break;
443       }
444     }
445   }
446   return status;
447 }
448
449 /*----------------------------------------------------------------------*/