Commit | Line | Data |
---|---|---|
7fd59977 | 1 | #include <OpenGl_FontMgr.hxx> |
2 | ||
3 | #include <FTGLTextureFont.h> | |
4 | #include <FTLibrary.h> | |
5 | #include <FTFace.h> | |
6 | #include <Standard_Stream.hxx> | |
7 | ||
8 | #undef TRACE | |
9 | ||
10 | #define DEFAULT_FONT_HEIGHT 16 | |
11 | ||
12 | float h_scale = 0; | |
13 | ||
14 | void dump_texture( int id); | |
15 | ||
16 | class Font_DataMap: | |
17 | public NCollection_DataMap< Handle(TCollection_HAsciiString), | |
18 | Handle(TCollection_HAsciiString)> | |
19 | { | |
20 | public: | |
21 | inline Font_DataMap | |
22 | (const Standard_Integer NbBuckets = 1, | |
23 | const Handle(NCollection_BaseAllocator)& theAllocator = 0L) | |
24 | : NCollection_DataMap<Handle(TCollection_HAsciiString), | |
25 | Handle(TCollection_HAsciiString)> (NbBuckets, theAllocator) | |
26 | {} | |
27 | ||
28 | inline Font_DataMap (const Font_DataMap& theOther) | |
29 | : NCollection_DataMap<Handle(TCollection_HAsciiString), | |
30 | Handle(TCollection_HAsciiString)> (theOther) | |
31 | {} | |
32 | friend Standard_Boolean IsEqual( const Handle(TCollection_HAsciiString)& h1, | |
33 | const Handle(TCollection_HAsciiString)& h2 ); | |
34 | }; | |
35 | inline Standard_Boolean | |
36 | IsEqual( const Handle(TCollection_HAsciiString)& h1, | |
37 | const Handle(TCollection_HAsciiString)& h2 ) | |
38 | { | |
39 | return (!h1->IsLess(h2) && !h1->IsGreater(h2)); | |
40 | } | |
41 | ||
42 | OpenGl_FontMgr::OpenGl_FontMgr() | |
43 | : _CurrentFontId(-1), | |
44 | _XCurrentScale(1.f), | |
45 | _YCurrentScale(1.f) | |
46 | { | |
47 | } | |
48 | ||
49 | OpenGl_FontMgr* OpenGl_FontMgr::instance() | |
50 | { | |
51 | static OpenGl_FontMgr* _mgr = NULL; | |
52 | if ( _mgr == NULL ) | |
53 | { | |
54 | _mgr = new OpenGl_FontMgr(); | |
55 | _mgr->_initializeFontDB(); | |
56 | } | |
57 | return _mgr; | |
58 | } | |
59 | ||
60 | void OpenGl_FontMgr::_initializeFontDB() | |
61 | { | |
62 | Handle(OSD_FontMgr) fntMgr = OSD_FontMgr::GetInstance(); | |
63 | if ( !fntMgr.IsNull() ) { | |
64 | ||
65 | OSD_NListOfSystemFont fontList = fntMgr->GetAvalableFonts(); | |
66 | if ( fontList.Size() != 0 ) { | |
67 | ||
68 | OSD_NListOfSystemFont::Iterator it(fontList); | |
69 | for ( ; it.More(); it.Next() ) { | |
70 | OGLFont_SysInfo* info = new OGLFont_SysInfo(); | |
71 | if ( it.Value()->FontAspect() == OSD_FA_Regular ) { | |
72 | //this workaround for fonts with names dependent on system locale. | |
73 | //for example: "Times New Roman Fett Kursive" or "Times New Roman Gras Italiqui" | |
74 | FTFace face(it.Value()->FontPath()->ToCString()); | |
75 | ||
76 | if ( face.Error() == FT_Err_Ok ) { | |
77 | if ( (*face.Face())->style_flags == 0 ) { | |
78 | info->SysFont = it.Value(); | |
79 | } | |
80 | else { | |
81 | //new aspect detected for current font item | |
82 | #ifdef TRACE | |
83 | cout << "TKOpenGl::initializeFontDB() detected new font!\n" | |
84 | << "\tFont Previous Name: " << it.Value()->FontName()->ToCString() << endl | |
85 | << "\tFont New Name: " << (*face.Face())->family_name << endl | |
86 | << "\tFont Aspect: " << (*face.Face())->style_flags << endl; | |
87 | #endif | |
88 | OSD_FontAspect aspect = OSD_FA_Regular; | |
89 | if ( (*face.Face())->style_flags == (FT_STYLE_FLAG_ITALIC | FT_STYLE_FLAG_BOLD) ) | |
90 | aspect = OSD_FA_BoldItalic; | |
91 | else if ( (*face.Face())->style_flags == FT_STYLE_FLAG_ITALIC ) | |
92 | aspect = OSD_FA_Italic; | |
93 | else if ( (*face.Face())->style_flags == FT_STYLE_FLAG_BOLD ) | |
94 | aspect = OSD_FA_Bold; | |
95 | ||
96 | #ifdef TRACE | |
97 | cout << "\tOSD_FontAspect: " << aspect << endl; | |
98 | #endif | |
99 | Handle(TCollection_HAsciiString) aFontName = | |
100 | new TCollection_HAsciiString( (*face.Face())->family_name ); | |
101 | info->SysFont = new OSD_SystemFont( aFontName, aspect, it.Value()->FontPath() ); | |
102 | } | |
103 | } | |
104 | else | |
105 | continue; | |
106 | } else { | |
107 | info->SysFont = it.Value(); | |
108 | } | |
109 | _FontDB.Append(info); | |
110 | ||
111 | } | |
112 | } | |
113 | } | |
114 | ||
115 | #ifdef TRACE | |
116 | if ( !_FontDB.Size() ) { | |
117 | cout << "\nTKOpenGl::initializeFontDB() FAILED!!!\n" | |
118 | << "No fonts detected in the system!\n" | |
119 | << "Text rendering in 3D viewer will not be available." << endl; | |
120 | } | |
121 | #endif | |
122 | } | |
123 | ||
124 | bool OpenGl_FontMgr::requestFontList( Graphic3d_NListOfHAsciiString& lst) | |
125 | { | |
126 | FontDBIt DBit(_FontDB); | |
127 | lst.Clear(); | |
128 | for ( ; DBit.More(); DBit.Next() ) { | |
129 | lst.Append( DBit.Value()->SysFont->FontName() ); | |
130 | } | |
131 | return true; | |
132 | } | |
133 | ||
134 | // Empty fontName means that ANY family name can be used. | |
135 | // fontAspect == OSD_FA_Undefined means ANY font aspect is acceptable. | |
136 | // fontheight == -1 means ANY font height is acceptable. | |
137 | int OpenGl_FontMgr::request_font( const Handle(TCollection_HAsciiString)& fontName, | |
138 | const OSD_FontAspect fontAspect, | |
139 | const Standard_Integer fontHeight ) | |
140 | { | |
141 | Standard_Integer aFontHeight = fontHeight; | |
142 | if ( aFontHeight < 2 && aFontHeight != -1 ) | |
143 | { | |
144 | #ifdef TRACE | |
145 | cout << "TKOpenGl::request_font\n" | |
146 | << " Error: font height is invalid!!!\n" | |
147 | << " font height:" << aFontHeight << "\n"; | |
148 | #endif //TRACE | |
149 | return -1; | |
150 | } | |
151 | ||
152 | #ifdef TRACE | |
153 | cout << "TKOpenGl::request_font\n" | |
154 | << " font name: " << fontName->ToCString() << endl | |
155 | << " font aspect: " << fontAspect << endl | |
156 | << " font height: " << aFontHeight << endl; | |
157 | #endif | |
158 | ||
159 | GLCONTEXT ctx = GET_GL_CONTEXT(); | |
160 | ||
161 | //check for font | |
162 | FontDBIt DBit(_FontDB); | |
163 | ||
164 | #ifdef TRACE | |
165 | cout << "Searching font in font database...\n"; | |
166 | #endif | |
167 | ||
168 | for ( ; DBit.More(); DBit.Next() ) { | |
169 | // san (23.07.2010): comparing font names in case-insensitive mode, | |
170 | // as on SUN and SGI system font names are in lower-case | |
171 | if ( fontName->IsEmpty() || DBit.Value()->SysFont->FontName()->IsSameString(fontName, Standard_False) ) { | |
172 | #ifdef TRACE | |
173 | cout << "\tName is found...\n\tCheking aspect...\n"; | |
174 | #endif | |
175 | ||
176 | //check for font aspect | |
177 | if (fontAspect != OSD_FA_Undefined && DBit.Value()->SysFont->FontAspect() != fontAspect) { | |
178 | #ifdef TRACE | |
179 | cout << "\tAspect of candidate font: " << DBit.Value()->SysFont->FontAspect() << endl; | |
180 | cout << "\tAspects are not equal! Continue seaching...\n"; | |
181 | #endif | |
182 | continue; | |
183 | } | |
184 | ||
185 | #ifdef TRACE | |
186 | cout << "\tAspect is found...\n\tCheking height...\n"; | |
187 | #endif | |
188 | //check for fixed height | |
189 | if (DBit.Value()->SysFont->FontHeight() != -1) { | |
190 | #ifdef TRACE | |
191 | cout << "\tChecking fixed height: " << DBit.Value()->SysFont->FontHeight() << endl; | |
192 | #endif | |
193 | //fixed height font | |
194 | if ( aFontHeight != -1 && DBit.Value()->SysFont->FontHeight() != aFontHeight ){ | |
195 | #ifdef TRACE | |
196 | cout << "\tHeights are not equal! Continue seaching...\n"; | |
197 | #endif | |
198 | continue; | |
199 | } | |
200 | else | |
201 | { | |
202 | // We need to remember the font height to be used | |
203 | if ( aFontHeight == -1 ) | |
204 | aFontHeight = DBit.Value()->SysFont->FontHeight(); | |
205 | #ifdef TRACE | |
206 | cout << "\tHeight is found\n"; | |
207 | #endif | |
208 | } | |
209 | } | |
210 | else | |
211 | { | |
212 | // If font height is not specified -> use DEFAULT_FONT_HEIGHT for variable-height fonts | |
213 | if ( aFontHeight == -1 ) | |
214 | aFontHeight = DEFAULT_FONT_HEIGHT; | |
215 | #ifdef TRACE | |
216 | cout << "\tFont has variable height == -1. height is found\n"; | |
217 | #endif | |
218 | } | |
219 | #ifdef TRACE | |
220 | cout << "\tChecking font manager cache...\n"; | |
221 | #endif | |
222 | //check in loaded fonts | |
223 | IDList::Iterator fIt(DBit.Value()->GeneratedFonts); | |
224 | for ( ; fIt.More(); fIt.Next() ) { | |
225 | OGLFont_Cache cache = _FontCache.Find( fIt.Value() ); | |
226 | if ( cache.FontHeight == aFontHeight && cache.GlContext == ctx ) { | |
227 | //requested font is generated already | |
228 | ||
229 | #ifdef TRACE | |
230 | cout << "\tRequested font is generated already\n\tId = " ; | |
231 | cout << fIt.Value() << endl; | |
232 | #endif | |
233 | _CurrentFontId = fIt.Value(); | |
234 | return _CurrentFontId; | |
235 | } else { | |
236 | #ifdef TRACE | |
237 | cout << "\t\tHeights or contexts are not equal:\n" | |
238 | << "\t\t\tfont height: " << aFontHeight << "\tchache height: " << cache.FontHeight << endl | |
239 | << "\t\t\tfont context: " << ctx << "\tchache context: " << cache.GlContext << endl; | |
240 | cout << "\t\tContinue searching in cache...\n"; | |
241 | #endif | |
242 | } | |
243 | } | |
244 | #ifdef TRACE | |
245 | cout << "\tRequested font is not found among genarated fonts.\n\tCreating new...\n"; | |
246 | #endif | |
247 | //if not found in generated fonts | |
248 | //create new | |
249 | FTGLTextureFont* font = new FTGLTextureFont(DBit.Value()->SysFont->FontPath()->ToCString()); | |
250 | //by default creates regular font | |
251 | if ( ! font || font->Error() != FT_Err_Ok) { | |
252 | #ifdef TRACE | |
253 | cout << "\t\tError during creation FTGL font object!\n"; | |
254 | #endif | |
255 | return -1; | |
256 | } | |
257 | ||
258 | if ( ! font->FaceSize( aFontHeight) || font->Error() != FT_Err_Ok ){ | |
259 | #ifdef TRACE | |
260 | cout << "\t\tError during setup FTGL font height!\n"; | |
261 | #endif | |
262 | return -1; | |
263 | } | |
264 | font->UseDisplayList( false ); | |
265 | ||
266 | //put font to cache | |
267 | OGLFont_Cache cache; | |
268 | cache.Font = font; | |
269 | cache.FontHeight = aFontHeight; | |
270 | cache.GlContext = ctx; | |
271 | ||
272 | _CurrentFontId =_FontCache.Size() + 1; | |
273 | _FontCache.Bind( _CurrentFontId, cache ); | |
274 | DBit.Value()->GeneratedFonts.Append(_CurrentFontId); | |
275 | ||
276 | #ifdef TRACE | |
277 | cout << "TKOpenGl::Loaded New FTGL font:\n" | |
278 | << " font name: " << fontName->ToCString() << "\n" | |
279 | << " font aspect: "; | |
280 | ||
281 | switch( fontAspect ) | |
282 | { | |
283 | case OSD_FA_Bold: | |
284 | cout << "OSD_FA_Bold\n"; | |
285 | break; | |
286 | case OSD_FA_BoldItalic: | |
287 | cout << "OSD_FA_BoldItalic\n"; | |
288 | break; | |
289 | case OSD_FA_Italic: | |
290 | cout << "OSD_FA_Italic\n"; | |
291 | break; | |
292 | case OSD_FA_Regular: | |
293 | cout << "OSD_FA_Regular\n"; | |
294 | break; | |
295 | default: | |
296 | cout << "OSD_FA_Undefined\n"; | |
297 | break; | |
298 | } | |
299 | cout << " font height: "<<aFontHeight<<"\n"; | |
300 | cout << " font id: " << _CurrentFontId << "\n"; | |
301 | #endif | |
302 | ||
303 | return _CurrentFontId; | |
304 | } | |
305 | } | |
306 | //invalid family name | |
307 | #ifdef TRACE | |
308 | cout << "\n---Invalid Family Name!!!---\n"; | |
309 | #endif | |
310 | return -1; | |
311 | } | |
312 | ||
13a22457 S |
313 | void OpenGl_FontMgr::render_text( const Standard_Integer id, const wchar_t* text, |
314 | const Standard_Boolean is2d ) | |
7fd59977 | 315 | { |
316 | #ifdef TRACE | |
317 | cout << "TKOpenGl::render_text\n" | |
318 | << "\tfont id = " << id << endl | |
319 | << "\ttext = " << text << endl; | |
320 | #endif | |
321 | if ( text && _FontCache.IsBound( id ) ) { | |
322 | glMatrixMode( GL_MODELVIEW ); | |
323 | glPushMatrix(); | |
324 | ||
325 | glScalef( _XCurrentScale, _YCurrentScale, 1 ); | |
326 | glPushAttrib( GL_ENABLE_BIT ); | |
327 | ||
328 | GLboolean enableTexture = glIsEnabled(GL_TEXTURE_2D); | |
329 | GLboolean enableDepthTest = glIsEnabled(GL_DEPTH_TEST); | |
330 | ||
331 | if( !enableTexture ) | |
332 | glEnable(GL_TEXTURE_2D); | |
256d4320 A |
333 | if ( !is2d ) { |
334 | if ( !enableDepthTest ) | |
335 | glEnable(GL_DEPTH_TEST); | |
13a22457 | 336 | } |
256d4320 A |
337 | else if ( enableDepthTest ) { |
338 | glDisable(GL_DEPTH_TEST); | |
339 | } | |
7fd59977 | 340 | |
c320e557 A |
341 | GLint param; |
342 | glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, ¶m); | |
7fd59977 | 343 | |
344 | glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); | |
345 | glAlphaFunc(GL_GEQUAL, 0.285f); | |
346 | glEnable(GL_ALPHA_TEST); | |
347 | OGLFont_Cache cache = _FontCache.Find( id ); | |
348 | cache.Font->Render( text ); | |
349 | ||
c320e557 | 350 | glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, param); |
7fd59977 | 351 | |
352 | if( !enableTexture ) | |
353 | glDisable(GL_TEXTURE_2D); | |
354 | if( !enableDepthTest ) | |
355 | glDisable(GL_DEPTH_TEST); | |
356 | ||
7fd59977 | 357 | glPopAttrib(); |
358 | glMatrixMode( GL_MODELVIEW ); | |
359 | glPopMatrix(); | |
360 | } | |
361 | ||
362 | } | |
363 | ||
13a22457 S |
364 | void OpenGl_FontMgr::render_text ( const wchar_t* text, const Standard_Boolean is2d ) |
365 | { | |
256d4320 | 366 | render_text( _CurrentFontId, text, is2d ); |
7fd59977 | 367 | } |
368 | ||
13a22457 S |
369 | const FTFont* OpenGl_FontMgr::fontById (const Standard_Integer id) |
370 | { | |
7fd59977 | 371 | return _FontCache.IsBound( id ) ? _FontCache.Find( id ).Font: NULL; |
372 | } | |
373 | ||
13a22457 S |
374 | Standard_ShortReal OpenGl_FontMgr::computeWidth( const Standard_Integer id, const wchar_t* text ) |
375 | { | |
7fd59977 | 376 | if( !_FontCache.IsBound( id ) ) |
377 | return 0.f; | |
378 | ||
379 | OGLFont_Cache cache = _FontCache.Find( id ); | |
7fd59977 | 380 | |
13a22457 | 381 | Standard_ShortReal w = cache.Font->Advance( text ); |
7fd59977 | 382 | |
383 | return w; | |
384 | } | |
385 | ||
13a22457 S |
386 | void OpenGl_FontMgr::setCurrentScale (const Standard_ShortReal xScale, |
387 | const Standard_ShortReal yScale) | |
7fd59977 | 388 | { |
389 | _XCurrentScale = xScale; | |
390 | _YCurrentScale = yScale; | |
391 | } | |
392 | ||
393 | #include <AlienImage_BMPAlienData.hxx> | |
394 | #include <OSD_File.hxx> | |
395 | #include <OSD_Protection.hxx> | |
396 | #include <Aspect_GenericColorMap.hxx> | |
397 | #include <Image_ColorImage.hxx> | |
398 | #include <Quantity_Color.hxx> | |
399 | ||
13a22457 S |
400 | void dump_texture( int id) |
401 | { | |
7fd59977 | 402 | Handle(AlienImage_BMPAlienData) image = new AlienImage_BMPAlienData(); |
403 | ||
404 | if (!glIsTexture(id)) | |
405 | return; | |
406 | ||
407 | unsigned char* pixels = new unsigned char[8192*1024]; | |
408 | memset( pixels, 0, 8192*1024 ); | |
409 | static int index = 0; | |
410 | index++; | |
411 | ||
412 | glBindTexture(GL_TEXTURE_2D, id ); | |
413 | glGetTexImage( GL_TEXTURE_2D , | |
414 | 0, | |
415 | GL_ALPHA, | |
416 | GL_UNSIGNED_BYTE, | |
417 | pixels ); | |
418 | ||
419 | Handle(Image_ColorImage) anImage = new Image_ColorImage( 0, 0, 1024, 8192 ); | |
420 | ||
421 | Aspect_ColorPixel mark( Quantity_Color (0.,0.5,1., Quantity_TOC_RGB ) ), | |
422 | space( Quantity_Color (1.,1.,1., Quantity_TOC_RGB ) ); | |
423 | ||
424 | for( int i = 0; i < 1024; i++ ) { | |
425 | for (int j = 0; j < 8192; j++ ) | |
426 | if (pixels[i*8192+j]>0) { | |
427 | anImage->SetPixel( anImage->LowerX()+i, | |
428 | anImage->LowerY()+j, | |
429 | mark ); | |
430 | } | |
431 | else { | |
432 | anImage->SetPixel( anImage->LowerX()+i, | |
433 | anImage->LowerY()+j, | |
434 | space ); | |
435 | } | |
436 | } | |
437 | ||
438 | image->FromImage( anImage ); | |
439 | TCollection_AsciiString name( index ); | |
440 | name.Prepend( "D:\\Temp_image" ); | |
441 | name += ".bmp"; | |
442 | OSD_File file ( name ); | |
443 | file.Build( OSD_WriteOnly, OSD_Protection()); | |
444 | image->Write(file); | |
445 | file.Close(); | |
446 | delete []pixels; | |
447 | } |