Commit | Line | Data |
---|---|---|
2166f0fa SK |
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 | |
c320e557 | 313 | export_h = (float)fnt->FaceSize() / export_h; |
2166f0fa | 314 | glPopMatrix(); |
c320e557 | 315 | ExportText( str, is2d, x, y, z, aspect, param, (short)export_h ); |
2166f0fa SK |
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, | |
c320e557 | 331 | const OpenGl_AspectText *aspect, const OpenGl_TextParam *param, const short height) |
2166f0fa SK |
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 | } |