0022819: Redesign of OpenGl driver
[occt.git] / src / OpenGl / OpenGl_Display_1.cxx
1 // File:      OpenGl_Display_1.cxx
2 // Created:   25 October 2011
3 // Author:    Sergey ZERCHANINOV
4 // Copyright: OPEN CASCADE 2011
5
6 #include <OpenGl_Display.hxx>
7
8 #include <TCollection_AsciiString.hxx>
9 #include <TCollection_HAsciiString.hxx>
10
11 #include <OpenGl_FontMgr.hxx>
12
13 #include <OpenGl_AspectText.hxx>
14
15 #ifdef HAVE_GL2PS
16 #include <gl2ps.h>
17 #endif
18
19 /*-----------------------------------------------------------------------------*/
20 /*
21 * Prototypes variables statiques
22 */                                                 
23
24 struct FontMapNode
25 {
26   const char *    EnumName;
27   const char *    FontName;
28   OSD_FontAspect  FontAspect;
29 };
30
31 static const FontMapNode myFontMap[] =
32 {
33
34 #ifdef WNT
35
36   { "Courier"                  , "Courier New"    , OSD_FA_Regular },
37   { "Times-Roman"              , "Times New Roman", OSD_FA_Regular  },
38   { "Times-Bold"               , "Times New Roman", OSD_FA_Bold },
39   { "Times-Italic"             , "Times New Roman", OSD_FA_Italic  },
40   { "Times-BoldItalic"         , "Times New Roman", OSD_FA_BoldItalic  },
41   { "ZapfChancery-MediumItalic", "Script"         , OSD_FA_Regular  },
42   { "Symbol"                   , "Symbol"         , OSD_FA_Regular  },
43   { "ZapfDingbats"             , "WingDings"      , OSD_FA_Regular  },
44   { "Rock"                     , "Arial"          , OSD_FA_Regular  },
45   { "Iris"                     , "Lucida Console" , OSD_FA_Regular  }
46
47 #else   //X11
48
49   { "Courier"                  , "Courier"      , OSD_FA_Regular },
50   { "Times-Roman"              , "Times"        , OSD_FA_Regular  },
51   { "Times-Bold"               , "Times"        , OSD_FA_Bold },
52   { "Times-Italic"             , "Times"        , OSD_FA_Italic  },
53   { "Times-BoldItalic"         , "Times"        , OSD_FA_BoldItalic  },
54   { "Arial"                    , "Helvetica"    , OSD_FA_Regular  }, 
55   { "ZapfChancery-MediumItalic", "-adobe-itc zapf chancery-medium-i-normal--*-*-*-*-*-*-iso8859-1"              , OSD_FA_Regular  },
56   { "Symbol"                   , "-adobe-symbol-medium-r-normal--*-*-*-*-*-*-adobe-fontspecific"                , OSD_FA_Regular  },
57   { "ZapfDingbats"             , "-adobe-itc zapf dingbats-medium-r-normal--*-*-*-*-*-*-adobe-fontspecific"     , OSD_FA_Regular  },
58   { "Rock"                     , "-sgi-rock-medium-r-normal--*-*-*-*-p-*-iso8859-1"                             , OSD_FA_Regular  },
59   { "Iris"                     , "--iris-medium-r-normal--*-*-*-*-m-*-iso8859-1"                                , OSD_FA_Regular  }
60 #endif
61
62 };
63
64 #define NUM_FONT_ENTRIES (sizeof(myFontMap)/sizeof(FontMapNode))
65
66 /*-----------------------------------------------------------------------------*/
67
68 /*
69 *  Constants
70 */
71
72 #ifdef HAVE_GL2PS
73 void OpenGl_Display::getGL2PSFontName (const char *src_font, char *ps_font)
74 {
75   /* 
76   Convert font name used for rendering to some "good" font names
77   that produce good vector text 
78   */
79   static char const *family[] = {"Helvetica", "Courier", "Times"};
80   static char const *italic[] = {"Oblique", "Oblique", "Italic"};
81   static char const *base[] = {"", "", "-Roman"};
82
83   int font = 0;
84   int isBold = 0;
85   int isItalic = 0;
86
87   if( strstr( src_font, "Symbol" ) ){
88     sprintf( ps_font, "%s", "Symbol" );
89     return;
90   }
91
92   if( strstr( src_font, "ZapfDingbats" ) ){
93     sprintf( ps_font, "%s", "WingDings" );
94     return;
95   }
96
97   if ( strstr( src_font, "Courier" ) ){
98     font = 1;
99   }
100   else if ( strstr( src_font, "Times" ) ){
101     font = 2;
102   }
103
104   if ( strstr( src_font, "Bold" ) ){
105     isBold = 1;
106   }
107
108   if ( strstr( src_font, "Italic" ) || strstr( src_font, "Oblique" ) ){
109     isItalic = 1;
110   }
111
112   if ( isBold ){
113     sprintf( ps_font, "%s-%s", family[font], "Bold");
114     if ( isItalic ){
115       sprintf(ps_font, "%s%s", ps_font, italic[font]);
116     }
117   }
118   else if ( isItalic )
119   {
120     sprintf( ps_font, "%s-%s", family[font], italic[font] );
121   }
122   else
123   {
124     sprintf( ps_font, "%s%s", family[font], base[font] );
125   }
126 }
127 #endif
128
129 /*-----------------------------------------------------------------------------*/
130
131 /*
132 * Fonctions publiques 
133 */
134
135 /*-----------------------------------------------------------------------------*/
136
137 int OpenGl_Display::FindFont (const char* AFontName, const OSD_FontAspect AFontAspect,
138                              const int ABestSize, const float AXScale, const float AYScale)
139 {   
140   if (!AFontName)
141     return -1;
142
143   if (ABestSize != -1)
144     myFontSize = ABestSize;
145
146   OpenGl_FontMgr* mgr = OpenGl_FontMgr::instance();
147
148   Handle(TCollection_HAsciiString) family_name = new TCollection_HAsciiString(AFontName);
149   myFont = mgr->request_font( family_name, AFontAspect, myFontSize );
150
151   if( myFont == -1 )
152   {
153     //try to use font names mapping
154     FontMapNode newTempFont = myFontMap[0];
155     for ( int i = 0; i < NUM_FONT_ENTRIES; ++i )
156     {
157       if ( TCollection_AsciiString(myFontMap[i].EnumName).IsEqual( family_name->ToCString() ) )
158       {
159         newTempFont = myFontMap[i];
160         break;
161       }
162     }
163     family_name = new TCollection_HAsciiString(newTempFont.FontName);
164     myFont = mgr->request_font( family_name, newTempFont.FontAspect, myFontSize );
165   }
166
167   // Requested family name not found -> serach for any font family with given aspect and height
168   if ( myFont == -1 )
169   {
170     family_name = new TCollection_HAsciiString( "" );
171     myFont = mgr->request_font( family_name, AFontAspect, myFontSize );
172   }
173
174   // The last resort: trying to use ANY font available in the system
175   if ( myFont == -1 )
176   {
177     myFont = mgr->request_font( family_name, OSD_FA_Undefined, -1 );
178   }
179
180   if ( myFont != -1 )
181     mgr->setCurrentScale( AXScale, AYScale );
182
183   return myFont;
184 }
185
186 /*-----------------------------------------------------------------------------*/
187
188 void OpenGl_Display::StringSize (const wchar_t *str, int &width, int &ascent, int &descent)
189 {
190   ascent = 0;
191   descent = 0;
192   width = 0;
193   if (myFont != -1) {
194     OpenGl_FontMgr* mgr = OpenGl_FontMgr::instance();
195     const FTFont* font = mgr->fontById( myFont );
196     if ( font ) {
197       width = int( mgr->computeWidth( myFont, str ) );
198       ascent = int( font->Ascender() );
199       descent = int( font->Descender() );
200     }
201   }
202 }
203
204 /*-----------------------------------------------------------------------------*/
205
206 void OpenGl_Display::RenderText (const wchar_t* str, const int is2d, const float x, const float y, const float z,
207                                 const OpenGl_AspectText *aspect, const OpenGl_TextParam *param)
208 {
209   OpenGl_FontMgr* mgr = OpenGl_FontMgr::instance();
210   const FTFont* fnt = mgr->fontById( myFont );
211   if ( !fnt )
212     return; 
213
214   // FTFont changes texture state when it renders and computes size for the text
215   glPushAttrib(GL_TEXTURE_BIT);
216
217   int widthFont, ascentFont, descentFont;
218   StringSize( str, widthFont, ascentFont, descentFont );
219
220   GLdouble xdis = 0.;
221   switch (param->HAlign)
222   {
223     case Graphic3d_HTA_CENTER:
224       xdis = -0.5 * (GLdouble)widthFont;
225       break;
226     case Graphic3d_HTA_RIGHT:
227       xdis = -(GLdouble)widthFont;
228       break;
229     //case Graphic3d_HTA_LEFT:
230     //default: break;
231   }
232   GLdouble ydis = 0.;
233   switch (param->VAlign)
234   {
235     case Graphic3d_VTA_CENTER:
236       ydis = -0.5 * (GLdouble)ascentFont - descentFont;
237       break;
238     case Graphic3d_VTA_TOP:
239       ydis = -(GLdouble)ascentFont - descentFont;
240       break;
241     //case Graphic3d_VTA_BOTTOM:
242     //default: break;
243   }
244
245   float export_h = 1.;
246
247   glMatrixMode(GL_MODELVIEW);
248   glPushMatrix();
249   if (is2d)
250   {
251     glLoadIdentity();
252     glTranslatef(x, y, 0.f);
253     glRotatef( 180, 1, 0, 0 );
254   }
255   else
256   {
257     const GLdouble identityMatrix[4][4] =
258     {
259       {1.,0.,0.,0.},
260       {0.,1.,0.,0.},
261       {0.,0.,1.,0.},
262       {0.,0.,0.,1.}
263     };
264
265     GLdouble projMatrix[4][4], modelMatrix[4][4];
266     GLint viewport[4];
267
268     GLdouble wx, wy, wz;
269     GLdouble x1, y1, z1;
270     GLdouble x2, y2, z2;
271
272     glGetDoublev( GL_MODELVIEW_MATRIX, (GLdouble*)modelMatrix );
273     glGetDoublev( GL_PROJECTION_MATRIX, (GLdouble*)projMatrix );
274     glGetIntegerv( GL_VIEWPORT, (GLint*)viewport );
275
276     gluProject( x, y, z,
277       (GLdouble*)modelMatrix,
278       (GLdouble*)projMatrix,
279       (GLint*)viewport,
280       &wx, &wy, &wz );
281     glLoadIdentity();
282     gluUnProject( wx, wy, wz, 
283       (GLdouble*)identityMatrix, (GLdouble*)projMatrix, (GLint*)viewport,
284       &x1, &y1 , &z1 );    
285
286     GLdouble h = (GLdouble)fnt->FaceSize();
287
288     gluUnProject( wx, wy + h - 1., wz,
289       (GLdouble*)identityMatrix, (GLdouble*)projMatrix, (GLint*)viewport,
290       &x2, &y2, &z2 );
291
292     h = (y2-y1)/h;
293
294     glTranslated( x1, y1 , z1 );   
295     glRotated(aspect->Angle(), 0, 0, 1);
296     glTranslated(xdis, ydis, 0);  
297
298     if( !aspect->IsZoomable() )
299     {
300       glScaled( h, h, h );
301     }
302     else
303     {
304       export_h = (float )h;
305     }
306   }
307
308   GLint renderMode;  
309   glGetIntegerv(GL_RENDER_MODE, &renderMode);
310   if ( renderMode == GL_FEEDBACK ) 
311   {
312 #ifdef HAVE_GL2PS
313     export_h = (GLdouble)fnt->FaceSize() / export_h;
314     glPopMatrix();
315     ExportText( str, is2d, x, y, z, aspect, param, export_h );
316 #endif
317   }
318   else
319   {
320     mgr->render_text( myFont, str, is2d );
321     glPopMatrix();
322   }
323   glPopAttrib();
324 }
325
326 /*-----------------------------------------------------------------------------*/
327
328 static const int alignmentforgl2ps[3][3] = { {5,2,8}, {4,1,7}, {6,3,9} };
329
330 void OpenGl_Display::ExportText (const wchar_t* text, const int is2d, const float x, const float y, const float z,
331                                 const OpenGl_AspectText *aspect, const OpenGl_TextParam *param, const float height)
332 {
333 #ifdef HAVE_GL2PS
334
335   int vh = 1;
336   switch (param->HAlign)
337   {
338     case Graphic3d_HTA_CENTER: vh = 2; break;
339     case Graphic3d_HTA_RIGHT: vh = 3; break;
340     //case Graphic3d_HTA_LEFT:
341     //default: break;
342   }
343
344   int vv = 1;
345   switch (param->VAlign)
346   {
347     case Graphic3d_VTA_CENTER: vv = 2; break;
348     case Graphic3d_VTA_TOP: vv = 3; break;
349     //case Graphic3d_VTA_BOTTOM:
350     //default: break;
351   }
352
353   const int alignment = alignmentforgl2ps[vh-1][vv-1];
354
355   const char* fontname = aspect->Font();
356   float angle = aspect->Angle();
357
358   GLubyte zero = 0;
359   char ps_font[64];
360
361   getGL2PSFontName(fontname, ps_font);
362
363   if( is2d )
364     glRasterPos2f( x, y );
365   else
366     glRasterPos3f( x, y, z );
367
368   glBitmap( 1, 1, 0, 0, 0, 0, &zero );
369
370   //szv: workaround for gl2ps!
371   const int len = 4 * (wcslen(text) + 1); //szv: should be more than enough
372   char *astr = new char[len];
373   wcstombs(astr,text,len);
374   gl2psTextOpt(astr, ps_font, height, alignment, angle);
375   delete[] astr;
376
377 #endif
378 }