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