Commit | Line | Data |
---|---|---|
b311480e | 1 | // Created on: 2011-10-25 |
2 | // Created by: Sergey ZERCHANINOV | |
3 | // Copyright (c) 2011-2012 OPEN CASCADE SAS | |
4 | // | |
5 | // The content of this file is subject to the Open CASCADE Technology Public | |
6 | // License Version 6.5 (the "License"). You may not use the content of this file | |
7 | // except in compliance with the License. Please obtain a copy of the License | |
8 | // at http://www.opencascade.org and read it completely before using this file. | |
9 | // | |
10 | // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its | |
11 | // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. | |
12 | // | |
13 | // The Original Code and all software distributed under the License is | |
14 | // distributed on an "AS IS" basis, without warranty of any kind, and the | |
15 | // Initial Developer hereby disclaims all such warranties, including without | |
16 | // limitation, any warranties of merchantability, fitness for a particular | |
17 | // purpose or non-infringement. Please see the License for the specific terms | |
18 | // and conditions governing the rights and limitations under the License. | |
19 | ||
2166f0fa | 20 | |
34a44cbd | 21 | #include <OpenGl_tgl_all.hxx> |
2166f0fa SK |
22 | #include <OpenGl_Display.hxx> |
23 | ||
24 | #include <TCollection_AsciiString.hxx> | |
25 | #include <TCollection_HAsciiString.hxx> | |
26 | ||
27 | #include <OpenGl_FontMgr.hxx> | |
34a44cbd | 28 | #include <OpenGl_PrinterContext.hxx> |
2166f0fa SK |
29 | #include <OpenGl_AspectText.hxx> |
30 | ||
31 | #ifdef HAVE_GL2PS | |
32 | #include <gl2ps.h> | |
33 | #endif | |
34 | ||
35 | /*-----------------------------------------------------------------------------*/ | |
36 | /* | |
37 | * Prototypes variables statiques | |
38 | */ | |
39 | ||
40 | struct FontMapNode | |
41 | { | |
42 | const char * EnumName; | |
43 | const char * FontName; | |
44 | OSD_FontAspect FontAspect; | |
45 | }; | |
46 | ||
47 | static const FontMapNode myFontMap[] = | |
48 | { | |
49 | ||
50 | #ifdef WNT | |
51 | ||
52 | { "Courier" , "Courier New" , OSD_FA_Regular }, | |
53 | { "Times-Roman" , "Times New Roman", OSD_FA_Regular }, | |
54 | { "Times-Bold" , "Times New Roman", OSD_FA_Bold }, | |
55 | { "Times-Italic" , "Times New Roman", OSD_FA_Italic }, | |
56 | { "Times-BoldItalic" , "Times New Roman", OSD_FA_BoldItalic }, | |
57 | { "ZapfChancery-MediumItalic", "Script" , OSD_FA_Regular }, | |
58 | { "Symbol" , "Symbol" , OSD_FA_Regular }, | |
59 | { "ZapfDingbats" , "WingDings" , OSD_FA_Regular }, | |
60 | { "Rock" , "Arial" , OSD_FA_Regular }, | |
61 | { "Iris" , "Lucida Console" , OSD_FA_Regular } | |
62 | ||
63 | #else //X11 | |
64 | ||
65 | { "Courier" , "Courier" , OSD_FA_Regular }, | |
66 | { "Times-Roman" , "Times" , OSD_FA_Regular }, | |
67 | { "Times-Bold" , "Times" , OSD_FA_Bold }, | |
68 | { "Times-Italic" , "Times" , OSD_FA_Italic }, | |
69 | { "Times-BoldItalic" , "Times" , OSD_FA_BoldItalic }, | |
70 | { "Arial" , "Helvetica" , OSD_FA_Regular }, | |
71 | { "ZapfChancery-MediumItalic", "-adobe-itc zapf chancery-medium-i-normal--*-*-*-*-*-*-iso8859-1" , OSD_FA_Regular }, | |
72 | { "Symbol" , "-adobe-symbol-medium-r-normal--*-*-*-*-*-*-adobe-fontspecific" , OSD_FA_Regular }, | |
73 | { "ZapfDingbats" , "-adobe-itc zapf dingbats-medium-r-normal--*-*-*-*-*-*-adobe-fontspecific" , OSD_FA_Regular }, | |
74 | { "Rock" , "-sgi-rock-medium-r-normal--*-*-*-*-p-*-iso8859-1" , OSD_FA_Regular }, | |
75 | { "Iris" , "--iris-medium-r-normal--*-*-*-*-m-*-iso8859-1" , OSD_FA_Regular } | |
76 | #endif | |
77 | ||
78 | }; | |
79 | ||
80 | #define NUM_FONT_ENTRIES (sizeof(myFontMap)/sizeof(FontMapNode)) | |
81 | ||
82 | /*-----------------------------------------------------------------------------*/ | |
83 | ||
84 | /* | |
85 | * Constants | |
86 | */ | |
87 | ||
88 | #ifdef HAVE_GL2PS | |
89 | void OpenGl_Display::getGL2PSFontName (const char *src_font, char *ps_font) | |
90 | { | |
91 | /* | |
92 | Convert font name used for rendering to some "good" font names | |
93 | that produce good vector text | |
94 | */ | |
95 | static char const *family[] = {"Helvetica", "Courier", "Times"}; | |
96 | static char const *italic[] = {"Oblique", "Oblique", "Italic"}; | |
97 | static char const *base[] = {"", "", "-Roman"}; | |
98 | ||
99 | int font = 0; | |
100 | int isBold = 0; | |
101 | int isItalic = 0; | |
102 | ||
103 | if( strstr( src_font, "Symbol" ) ){ | |
104 | sprintf( ps_font, "%s", "Symbol" ); | |
105 | return; | |
106 | } | |
107 | ||
108 | if( strstr( src_font, "ZapfDingbats" ) ){ | |
109 | sprintf( ps_font, "%s", "WingDings" ); | |
110 | return; | |
111 | } | |
112 | ||
113 | if ( strstr( src_font, "Courier" ) ){ | |
114 | font = 1; | |
115 | } | |
116 | else if ( strstr( src_font, "Times" ) ){ | |
117 | font = 2; | |
118 | } | |
119 | ||
120 | if ( strstr( src_font, "Bold" ) ){ | |
121 | isBold = 1; | |
122 | } | |
123 | ||
124 | if ( strstr( src_font, "Italic" ) || strstr( src_font, "Oblique" ) ){ | |
125 | isItalic = 1; | |
126 | } | |
127 | ||
128 | if ( isBold ){ | |
129 | sprintf( ps_font, "%s-%s", family[font], "Bold"); | |
130 | if ( isItalic ){ | |
131 | sprintf(ps_font, "%s%s", ps_font, italic[font]); | |
132 | } | |
133 | } | |
134 | else if ( isItalic ) | |
135 | { | |
136 | sprintf( ps_font, "%s-%s", family[font], italic[font] ); | |
137 | } | |
138 | else | |
139 | { | |
140 | sprintf( ps_font, "%s%s", family[font], base[font] ); | |
141 | } | |
142 | } | |
143 | #endif | |
144 | ||
145 | /*-----------------------------------------------------------------------------*/ | |
146 | ||
147 | /* | |
148 | * Fonctions publiques | |
149 | */ | |
150 | ||
151 | /*-----------------------------------------------------------------------------*/ | |
152 | ||
153 | int OpenGl_Display::FindFont (const char* AFontName, const OSD_FontAspect AFontAspect, | |
154 | const int ABestSize, const float AXScale, const float AYScale) | |
155 | { | |
156 | if (!AFontName) | |
157 | return -1; | |
158 | ||
159 | if (ABestSize != -1) | |
160 | myFontSize = ABestSize; | |
161 | ||
162 | OpenGl_FontMgr* mgr = OpenGl_FontMgr::instance(); | |
163 | ||
164 | Handle(TCollection_HAsciiString) family_name = new TCollection_HAsciiString(AFontName); | |
165 | myFont = mgr->request_font( family_name, AFontAspect, myFontSize ); | |
166 | ||
167 | if( myFont == -1 ) | |
168 | { | |
169 | //try to use font names mapping | |
170 | FontMapNode newTempFont = myFontMap[0]; | |
171 | for ( int i = 0; i < NUM_FONT_ENTRIES; ++i ) | |
172 | { | |
173 | if ( TCollection_AsciiString(myFontMap[i].EnumName).IsEqual( family_name->ToCString() ) ) | |
174 | { | |
175 | newTempFont = myFontMap[i]; | |
176 | break; | |
177 | } | |
178 | } | |
179 | family_name = new TCollection_HAsciiString(newTempFont.FontName); | |
180 | myFont = mgr->request_font( family_name, newTempFont.FontAspect, myFontSize ); | |
181 | } | |
182 | ||
183 | // Requested family name not found -> serach for any font family with given aspect and height | |
184 | if ( myFont == -1 ) | |
185 | { | |
186 | family_name = new TCollection_HAsciiString( "" ); | |
187 | myFont = mgr->request_font( family_name, AFontAspect, myFontSize ); | |
188 | } | |
189 | ||
190 | // The last resort: trying to use ANY font available in the system | |
191 | if ( myFont == -1 ) | |
192 | { | |
193 | myFont = mgr->request_font( family_name, OSD_FA_Undefined, -1 ); | |
194 | } | |
195 | ||
196 | if ( myFont != -1 ) | |
197 | mgr->setCurrentScale( AXScale, AYScale ); | |
198 | ||
199 | return myFont; | |
200 | } | |
201 | ||
202 | /*-----------------------------------------------------------------------------*/ | |
203 | ||
204 | void OpenGl_Display::StringSize (const wchar_t *str, int &width, int &ascent, int &descent) | |
205 | { | |
206 | ascent = 0; | |
207 | descent = 0; | |
208 | width = 0; | |
209 | if (myFont != -1) { | |
210 | OpenGl_FontMgr* mgr = OpenGl_FontMgr::instance(); | |
211 | const FTFont* font = mgr->fontById( myFont ); | |
212 | if ( font ) { | |
213 | width = int( mgr->computeWidth( myFont, str ) ); | |
214 | ascent = int( font->Ascender() ); | |
215 | descent = int( font->Descender() ); | |
216 | } | |
217 | } | |
218 | } | |
219 | ||
f3f08423 | 220 | /* |
221 | Class : MultilineTextRenderer | |
222 | Description : Class for constructing text and multi-line text | |
223 | */ | |
224 | ||
225 | class MultilineTextRenderer | |
226 | { | |
227 | private: | |
228 | ||
229 | Standard_Integer myLFNum; // Number of '\n' (Line Feed) '\x00\x0A' | |
230 | Standard_Integer myCurrPos; // Position of the current substring | |
231 | Standard_Integer myNewStrLen; // Length of the new string | |
232 | Standard_Integer mySubstrNum; // Number of substrings | |
233 | wchar_t *myNewStr; // New string | |
234 | const wchar_t *myStrPtr; // Pointer to the original string | |
235 | ||
236 | public: | |
237 | ||
238 | // ---------------------------------------------- | |
239 | // Function: MultilineTextRenderer | |
240 | // Purpose: Constructor with initialization | |
241 | // ---------------------------------------------- | |
242 | MultilineTextRenderer ( const wchar_t *theStr, | |
243 | GLdouble &theXdis, | |
244 | GLdouble &theYdis, | |
245 | const OpenGl_TextParam *theParam, | |
246 | const FTFont *theFnt, | |
247 | GLint theWidthFont, | |
248 | GLint theAscentFont, | |
249 | GLint theDescentFont ) : | |
250 | ||
251 | myLFNum (0), | |
252 | myCurrPos (0), | |
253 | myNewStrLen (0), | |
254 | mySubstrNum (0), | |
255 | myNewStr (0), | |
256 | myStrPtr (&theStr[0]) | |
257 | { | |
258 | const Standard_Integer aStrLen = wcslen(theStr); // Length of the original string | |
259 | Standard_Integer aNextCRChar = 0; // Character after '\r' (Carriage Return) '\x00\x0D' | |
260 | Standard_Integer aHTNum = 0; // Number of '\t' (Horizontal Tabulation) '\x00\x09' | |
261 | Standard_Integer aDumpNum = 0; // Number of '\a', '\b', '\v' and '\f' | |
262 | Standard_Integer anAllSpaces = 0; // Number of spaces instead of all '\t' characters | |
263 | Standard_Integer aMaxSubstrLen = 0; // Length of the largest substring in the new string | |
264 | ||
265 | Standard_Integer aTimeVar = 0; | |
266 | ||
267 | // Calculation index after last '\r' character | |
268 | for ( Standard_Integer anIndex = 0; anIndex < aStrLen; ++anIndex ) | |
269 | { | |
270 | if ( theStr[anIndex] == '\r' ) aNextCRChar = anIndex+1; | |
271 | } | |
272 | ||
273 | // Calculation numbers of the some control characters | |
274 | for (Standard_Integer anIndex = aNextCRChar; anIndex < aStrLen; anIndex++) | |
275 | { | |
276 | ++aTimeVar; | |
277 | switch ( theStr[anIndex] ) | |
278 | { | |
279 | case '\n': | |
280 | ++myLFNum; | |
281 | aTimeVar = 0; | |
282 | break; | |
283 | case '\b': | |
284 | case '\v': | |
285 | case '\f': | |
286 | case '\a': | |
287 | ++aDumpNum; | |
288 | --aTimeVar; | |
289 | break; | |
290 | case '\t': | |
291 | ++aHTNum; | |
292 | anAllSpaces += ( 8 - ( aTimeVar - 1 )%8 ); | |
293 | aTimeVar = 0; | |
294 | break; | |
295 | } | |
296 | } | |
297 | ||
298 | // Calculation length of the new string | |
299 | myStrPtr += aNextCRChar; | |
300 | myNewStrLen = aStrLen - aNextCRChar + anAllSpaces - aHTNum - aDumpNum; | |
301 | ||
302 | myNewStr = new wchar_t[myNewStrLen + 1]; | |
303 | myNewStr[myNewStrLen]='\0'; | |
304 | ||
305 | CalcString (aStrLen, aMaxSubstrLen); | |
306 | CalcHAlign (theXdis, theParam, theWidthFont, aStrLen, aMaxSubstrLen); | |
307 | CalcVAlign (theYdis, theParam, theFnt, theAscentFont, theDescentFont); | |
308 | } | |
309 | ||
310 | // ---------------------------------------------- | |
311 | // Function: ~MultilineTextRenderer | |
312 | // Purpose: Default destructor | |
313 | // ---------------------------------------------- | |
314 | ~MultilineTextRenderer () | |
315 | { | |
316 | delete[] myNewStr; | |
317 | } | |
318 | ||
319 | // ---------------------------------------------- | |
320 | // Function: Next | |
321 | // Purpose: Calculate position of the next substring | |
322 | // ---------------------------------------------- | |
323 | void Next () | |
324 | { | |
325 | for ( Standard_Integer anIndex = 0; anIndex <= myNewStrLen; ++anIndex ) | |
326 | { | |
327 | if ( myNewStr[myCurrPos + anIndex] == '\0' ) | |
328 | { | |
329 | ++mySubstrNum; | |
330 | myCurrPos += anIndex + 1; | |
331 | break; | |
332 | } | |
333 | } | |
334 | } | |
335 | ||
336 | // ---------------------------------------------- | |
337 | // Function: More | |
338 | // Purpose: Calculate position of the next substring | |
339 | // ---------------------------------------------- | |
340 | Standard_Boolean More () | |
341 | { | |
342 | if ( mySubstrNum <= myLFNum ) return Standard_True; | |
343 | else return Standard_False; | |
344 | } | |
345 | ||
346 | // ---------------------------------------------- | |
347 | // Function: GetValue | |
348 | // Purpose: Returns current substring | |
349 | // ---------------------------------------------- | |
350 | wchar_t* GetValue () | |
351 | { | |
352 | return ( myNewStr + myCurrPos ); | |
353 | } | |
354 | ||
355 | private: | |
356 | ||
357 | // ---------------------------------------------- | |
358 | // Function: CalcString | |
359 | // Purpose: Calculate new string separated by '\0' without '\n', '\t', '\b', '\v', '\f', '\a' | |
360 | // ---------------------------------------------- | |
361 | void CalcString ( const Standard_Integer theStrLen, Standard_Integer &theMaxSubstrLen ) | |
362 | { | |
363 | Standard_Integer | |
364 | aHelpIndex = 0, | |
365 | aTimeVar = 0, | |
366 | aSpacesNum = 0; | |
367 | ||
368 | for ( Standard_Integer anIndex1 = 0, anIndex2 = 0; | |
369 | (anIndex1 < theStrLen)&&(anIndex2 < myNewStrLen); | |
370 | ++anIndex1, ++anIndex2 ) | |
371 | { | |
372 | ++aTimeVar; | |
373 | ||
374 | if ( *(myStrPtr + anIndex1) == '\n' ) aTimeVar = 0; | |
375 | ||
376 | while ( (*(myStrPtr + anIndex1)=='\b')||(*(myStrPtr + anIndex1)=='\f') | |
377 | ||(*(myStrPtr + anIndex1)=='\v')||(*(myStrPtr + anIndex1)=='\a') ) | |
378 | { | |
379 | ++anIndex1; | |
380 | } | |
381 | ||
382 | if ( *(myStrPtr + anIndex1) == '\t' ) | |
383 | { | |
384 | aSpacesNum = ( 8 - ( aTimeVar - 1 )%8 ); | |
385 | ||
386 | for ( aHelpIndex = 0; aHelpIndex < aSpacesNum; aHelpIndex++ ) | |
387 | { | |
388 | myNewStr[anIndex2 + aHelpIndex] = ' '; | |
389 | } | |
390 | anIndex2 += aHelpIndex - 1; | |
391 | aTimeVar = 0; | |
392 | } | |
393 | else | |
394 | { | |
395 | myNewStr[anIndex2] = *(myStrPtr + anIndex1); | |
396 | } | |
397 | } | |
398 | ||
399 | // After this part of code we will have a string separated by '\0' characters | |
400 | Standard_Integer aHelpLength = 0; | |
401 | ||
402 | if( myNewStr ) | |
403 | { | |
404 | for( Standard_Integer anIndex = 0; anIndex <= myNewStrLen; ++anIndex ) | |
405 | { | |
406 | if ( myNewStr[anIndex] == '\n' ) | |
407 | { | |
408 | myNewStr[anIndex] = '\0'; | |
409 | } | |
410 | ||
411 | // Calculating length of the largest substring of the new string. | |
412 | // It's needed for horizontal alignment | |
413 | if ( myNewStr[anIndex] != '\0' ) | |
414 | { | |
415 | ++aHelpLength; | |
416 | } | |
417 | else | |
418 | { | |
419 | if ( aHelpLength > theMaxSubstrLen ) theMaxSubstrLen = aHelpLength; | |
420 | ||
421 | aHelpLength = 0; | |
422 | } | |
423 | } | |
424 | } | |
425 | } | |
426 | ||
427 | // ---------------------------------------------- | |
428 | // Function: CalcVAlign | |
429 | // Purpose: Calculate vertical alignment for text | |
430 | // ---------------------------------------------- | |
431 | void CalcVAlign ( GLdouble &theYdis, | |
432 | const OpenGl_TextParam *theParam, | |
433 | const FTFont *theFnt, | |
434 | GLint theAscentFont, | |
435 | GLint theDescentFont ) | |
436 | { | |
437 | switch (theParam->VAlign) | |
438 | { | |
439 | case Graphic3d_VTA_BOTTOM: | |
440 | theYdis = (GLdouble)(myLFNum * theFnt->FaceSize()); | |
441 | break; | |
442 | case Graphic3d_VTA_CENTER: | |
443 | if ( (myLFNum%2) == 0 ) // An odd number of strings | |
444 | { | |
445 | theYdis = (GLdouble)((myLFNum/2.0) * theFnt->FaceSize()) + theDescentFont; | |
446 | } | |
447 | else // An even number of strings | |
448 | { | |
449 | theYdis = (GLdouble)((myLFNum - 1)/2.0 * theFnt->FaceSize()) - theDescentFont/2.0; | |
450 | } | |
451 | break; | |
452 | case Graphic3d_VTA_TOP: | |
453 | theYdis = -(GLdouble)theAscentFont - theDescentFont; | |
454 | break; | |
455 | default: | |
456 | theYdis = (GLdouble)(myLFNum * theFnt->FaceSize()); | |
457 | break; | |
458 | } | |
459 | } | |
460 | ||
461 | // ---------------------------------------------- | |
462 | // Function: CalcHAlign | |
463 | // Purpose: Calculate horizontal alignment for text | |
464 | // ---------------------------------------------- | |
465 | void CalcHAlign ( GLdouble &theXdis, | |
466 | const OpenGl_TextParam *theParam, | |
467 | GLint theWidthFont, | |
468 | const Standard_Integer theStrLen, | |
469 | Standard_Integer theMaxSubstrLen) | |
470 | { | |
471 | GLdouble aWidth = (GLdouble)(theMaxSubstrLen * theWidthFont)/theStrLen; | |
472 | ||
473 | switch (theParam->HAlign) | |
474 | { | |
475 | case Graphic3d_HTA_LEFT: | |
476 | theXdis = 0.; | |
477 | break; | |
478 | case Graphic3d_HTA_CENTER: | |
479 | theXdis = -0.5 * (GLdouble)aWidth; | |
480 | break; | |
481 | case Graphic3d_HTA_RIGHT: | |
482 | theXdis = -(GLdouble)aWidth; | |
483 | break; | |
484 | default: | |
485 | theXdis = 0.; | |
486 | break; | |
487 | } | |
488 | } | |
489 | }; | |
490 | ||
2166f0fa SK |
491 | /*-----------------------------------------------------------------------------*/ |
492 | ||
493 | void OpenGl_Display::RenderText (const wchar_t* str, const int is2d, const float x, const float y, const float z, | |
494 | const OpenGl_AspectText *aspect, const OpenGl_TextParam *param) | |
495 | { | |
496 | OpenGl_FontMgr* mgr = OpenGl_FontMgr::instance(); | |
497 | const FTFont* fnt = mgr->fontById( myFont ); | |
498 | if ( !fnt ) | |
499 | return; | |
500 | ||
501 | // FTFont changes texture state when it renders and computes size for the text | |
502 | glPushAttrib(GL_TEXTURE_BIT); | |
503 | ||
504 | int widthFont, ascentFont, descentFont; | |
505 | StringSize( str, widthFont, ascentFont, descentFont ); | |
506 | ||
f3f08423 | 507 | GLdouble xdis = 0., ydis = 0.; |
2166f0fa SK |
508 | |
509 | float export_h = 1.; | |
510 | ||
f3f08423 | 511 | MultilineTextRenderer aRenderer( str, |
512 | xdis, | |
513 | ydis, | |
514 | param, | |
515 | fnt, | |
516 | widthFont, | |
517 | ascentFont, | |
518 | descentFont ); | |
519 | ||
2166f0fa SK |
520 | glMatrixMode(GL_MODELVIEW); |
521 | glPushMatrix(); | |
522 | if (is2d) | |
523 | { | |
524 | glLoadIdentity(); | |
525 | glTranslatef(x, y, 0.f); | |
526 | glRotatef( 180, 1, 0, 0 ); | |
527 | } | |
528 | else | |
529 | { | |
530 | const GLdouble identityMatrix[4][4] = | |
531 | { | |
532 | {1.,0.,0.,0.}, | |
533 | {0.,1.,0.,0.}, | |
534 | {0.,0.,1.,0.}, | |
535 | {0.,0.,0.,1.} | |
536 | }; | |
537 | ||
538 | GLdouble projMatrix[4][4], modelMatrix[4][4]; | |
539 | GLint viewport[4]; | |
540 | ||
541 | GLdouble wx, wy, wz; | |
542 | GLdouble x1, y1, z1; | |
543 | GLdouble x2, y2, z2; | |
544 | ||
545 | glGetDoublev( GL_MODELVIEW_MATRIX, (GLdouble*)modelMatrix ); | |
546 | glGetDoublev( GL_PROJECTION_MATRIX, (GLdouble*)projMatrix ); | |
547 | glGetIntegerv( GL_VIEWPORT, (GLint*)viewport ); | |
548 | ||
549 | gluProject( x, y, z, | |
550 | (GLdouble*)modelMatrix, | |
551 | (GLdouble*)projMatrix, | |
552 | (GLint*)viewport, | |
553 | &wx, &wy, &wz ); | |
554 | glLoadIdentity(); | |
555 | gluUnProject( wx, wy, wz, | |
556 | (GLdouble*)identityMatrix, (GLdouble*)projMatrix, (GLint*)viewport, | |
557 | &x1, &y1 , &z1 ); | |
558 | ||
559 | GLdouble h = (GLdouble)fnt->FaceSize(); | |
560 | ||
561 | gluUnProject( wx, wy + h - 1., wz, | |
562 | (GLdouble*)identityMatrix, (GLdouble*)projMatrix, (GLint*)viewport, | |
563 | &x2, &y2, &z2 ); | |
564 | ||
565 | h = (y2-y1)/h; | |
566 | ||
567 | glTranslated( x1, y1 , z1 ); | |
568 | glRotated(aspect->Angle(), 0, 0, 1); | |
569 | glTranslated(xdis, ydis, 0); | |
570 | ||
571 | if( !aspect->IsZoomable() ) | |
572 | { | |
34a44cbd | 573 | #ifdef WNT |
574 | // if the context has assigned printer context, use it's parameters | |
575 | OpenGl_PrinterContext* aPrinterContext = | |
576 | OpenGl_PrinterContext::GetPrinterContext( GET_GL_CONTEXT() ); | |
577 | if( aPrinterContext ) | |
578 | { | |
579 | // get printing scaling in x and y dimensions | |
580 | GLfloat aTextScalex = 1, aTextScaley = 1; | |
581 | aPrinterContext->GetScale( aTextScalex, aTextScaley ); | |
582 | ||
583 | // text should be scaled in all directions with same | |
584 | // factor to save its proportions, so use height (y) scaling | |
585 | // as it is better for keeping text/3d graphics proportions | |
586 | glScalef( aTextScaley, aTextScaley, aTextScaley ); | |
587 | } | |
588 | #endif | |
2166f0fa SK |
589 | glScaled( h, h, h ); |
590 | } | |
591 | else | |
592 | { | |
f3f08423 | 593 | export_h = (float)h; |
2166f0fa SK |
594 | } |
595 | } | |
596 | ||
597 | GLint renderMode; | |
598 | glGetIntegerv(GL_RENDER_MODE, &renderMode); | |
599 | if ( renderMode == GL_FEEDBACK ) | |
600 | { | |
601 | #ifdef HAVE_GL2PS | |
c320e557 | 602 | export_h = (float)fnt->FaceSize() / export_h; |
f3f08423 | 603 | for ( ; aRenderer.More(); aRenderer.Next() ) |
604 | { | |
605 | // x, y, z coordinates are used here as zero values, because position of the text | |
606 | // and alignment is calculated in the code above using glTranslated methods | |
607 | ExportText( aRenderer.GetValue(), is2d, 0, 0, 0, aspect, param, (short)export_h ); | |
608 | glTranslated(0, -(GLdouble)fnt->FaceSize(), 0); | |
609 | } | |
2166f0fa SK |
610 | #endif |
611 | } | |
612 | else | |
613 | { | |
f3f08423 | 614 | for ( ; aRenderer.More(); aRenderer.Next() ) |
615 | { | |
616 | mgr->render_text( myFont, aRenderer.GetValue(), is2d ); | |
617 | glTranslated(0, -(GLdouble)fnt->FaceSize(), 0); | |
618 | } | |
2166f0fa | 619 | } |
f3f08423 | 620 | glPopMatrix(); |
2166f0fa SK |
621 | glPopAttrib(); |
622 | } | |
623 | ||
624 | /*-----------------------------------------------------------------------------*/ | |
625 | ||
2166f0fa | 626 | void OpenGl_Display::ExportText (const wchar_t* text, const int is2d, const float x, const float y, const float z, |
c320e557 | 627 | const OpenGl_AspectText *aspect, const OpenGl_TextParam *param, const short height) |
2166f0fa SK |
628 | { |
629 | #ifdef HAVE_GL2PS | |
630 | ||
2166f0fa SK |
631 | const char* fontname = aspect->Font(); |
632 | float angle = aspect->Angle(); | |
633 | ||
634 | GLubyte zero = 0; | |
635 | char ps_font[64]; | |
636 | ||
637 | getGL2PSFontName(fontname, ps_font); | |
638 | ||
639 | if( is2d ) | |
640 | glRasterPos2f( x, y ); | |
641 | else | |
642 | glRasterPos3f( x, y, z ); | |
643 | ||
644 | glBitmap( 1, 1, 0, 0, 0, 0, &zero ); | |
645 | ||
646 | //szv: workaround for gl2ps! | |
647 | const int len = 4 * (wcslen(text) + 1); //szv: should be more than enough | |
648 | char *astr = new char[len]; | |
649 | wcstombs(astr,text,len); | |
f3f08423 | 650 | |
651 | // Standard GL2PS's alignment isn't used, because it doesn't work correctly | |
652 | // for all formats, therefore alignment is calculated manually relative | |
653 | // to the bottom-left corner, which corresponds to the GL2PS_TEXT_BL value | |
654 | gl2psTextOpt(astr, ps_font, height, GL2PS_TEXT_BL, angle); | |
2166f0fa SK |
655 | delete[] astr; |
656 | ||
657 | #endif | |
658 | } |