596355a18355085ad63008fb847bc88def600ae0
[occt.git] / src / OpenGl / OpenGl_FontMgr.cxx
1 // Copyright (c) 1999-2012 OPEN CASCADE SAS
2 //
3 // The content of this file is subject to the Open CASCADE Technology Public
4 // License Version 6.5 (the "License"). You may not use the content of this file
5 // except in compliance with the License. Please obtain a copy of the License
6 // at http://www.opencascade.org and read it completely before using this file.
7 //
8 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
9 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
10 //
11 // The Original Code and all software distributed under the License is
12 // distributed on an "AS IS" basis, without warranty of any kind, and the
13 // Initial Developer hereby disclaims all such warranties, including without
14 // limitation, any warranties of merchantability, fitness for a particular
15 // purpose or non-infringement. Please see the License for the specific terms
16 // and conditions governing the rights and limitations under the License.
17
18 #include <OpenGl_FontMgr.hxx>
19 #include <OpenGl_GlCore11.hxx>
20
21 #include <Standard_Stream.hxx>
22 #include <TColStd_SequenceOfHAsciiString.hxx>
23
24 #ifdef _MSC_VER
25 #pragma comment( lib, "ftgl.lib" )
26 #endif
27
28 #undef TRACE
29
30 #define DEFAULT_FONT_HEIGHT 16
31
32 float h_scale = 0;
33
34 void dump_texture( int id);
35
36 OpenGl_FontMgr::OpenGl_FontMgr()
37 : myCurrentFontId(-1),
38 myXCurrentScale(1.f),
39 myYCurrentScale(1.f) 
40 {
41 }
42
43 OpenGl_FontMgr* OpenGl_FontMgr::instance() 
44 {
45   static OpenGl_FontMgr* _mgr = NULL;
46   if ( _mgr == NULL )
47   {
48     _mgr = new OpenGl_FontMgr();
49   }
50   return _mgr;
51 }
52
53 // Empty fontName means that ANY family name can be used.
54 // fontAspect == Font_FA_Undefined means ANY font aspect is acceptable.
55 // fontheight == -1 means ANY font height is acceptable.
56 int OpenGl_FontMgr::request_font (const Handle(TCollection_HAsciiString)& theFontName,
57                                   const Font_FontAspect                   theFontAspect,
58                                   const Standard_Integer&                 theFontHeight)
59 {
60   Handle(Font_FontMgr) aFontMgr = Font_FontMgr::GetInstance();
61   Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFont (theFontName, theFontAspect, theFontHeight);
62
63   if (aRequestedFont.IsNull())
64   {
65     return -1;
66   }
67
68   // Setting font height
69   Standard_Integer aFontHeight = theFontHeight;
70   if (theFontHeight < 2 && aRequestedFont->FontHeight() == -1)
71   {
72     // Font height is not specified -> use DEFAULT_FONT_HEIGHT for variable-height fonts
73     aFontHeight = DEFAULT_FONT_HEIGHT;
74   }
75   else if (theFontHeight < 2)
76   {
77     // Font height is not specified -> use font height for fixed size fonts
78     aFontHeight = aRequestedFont->FontHeight();
79   }
80
81   GLCONTEXT aContext = GET_GL_CONTEXT();
82
83   // Check in already generated fonts.
84   if (myGeneratedFontDB.IsBound (aRequestedFont))
85   {
86     const IDList& anIDList = myGeneratedFontDB.Find (aRequestedFont);
87     for (IDList::Iterator anIDListIterator (anIDList); anIDListIterator.More();
88          anIDListIterator.Next())
89     {
90       OGLFont_Cache aFontCache = myGeneratedFontCache (anIDListIterator.Value());
91       if (aFontCache.FontHeight == aFontHeight && aFontCache.GlContext == aContext)
92       {
93         // Requested font is already generated, returning it cache ID.
94         myCurrentFontId = anIDListIterator.Value();
95         return myCurrentFontId;
96       }
97     }
98   }
99
100   // Cache for requested font is not found. Generating new FTGL font.
101   FTGLTextureFont* aFTGLFont = new FTGLTextureFont(aRequestedFont->FontPath()->ToCString());
102   if ( !aFTGLFont || aFTGLFont->Error() != FT_Err_Ok)
103   {
104     return -1; // Error during creation FTGL font object!
105   }
106
107   if ( !aFTGLFont->FaceSize (aFontHeight) || aFTGLFont->Error() != FT_Err_Ok )
108   {
109     return -1; // Error during setup FTGL font height!
110   }
111
112   aFTGLFont->UseDisplayList (false);
113
114   // Adding font to cache.
115   OGLFont_Cache aCache;
116   aCache.Font = aFTGLFont;
117   aCache.FontHeight = aFontHeight;
118   aCache.GlContext = aContext;
119
120   myCurrentFontId = myGeneratedFontCache.Size() + 1;
121   myGeneratedFontCache.Bind ( myCurrentFontId, aCache);
122
123   if (myGeneratedFontDB.IsBound (aRequestedFont))
124   {
125     myGeneratedFontDB.ChangeFind (aRequestedFont).Append (myCurrentFontId);
126   }
127   else
128   {
129     IDList anIDList;
130     anIDList.Append (myCurrentFontId);
131     myGeneratedFontDB.Bind (aRequestedFont, anIDList);
132   }
133
134   return myCurrentFontId;
135 }
136
137 void OpenGl_FontMgr::render_text( const Standard_Integer id, const wchar_t* text,
138                                   const Standard_Boolean is2d )
139 {
140 #ifdef TRACE
141   cout << "TKOpenGl::render_text\n"
142     << "\tfont id = " << id << endl
143     << "\ttext = " << text << endl;
144 #endif
145   if ( text && myGeneratedFontCache.IsBound( id ) ) {
146     glMatrixMode( GL_MODELVIEW );
147     glPushMatrix();
148
149     glScalef( myXCurrentScale, myYCurrentScale, 1 );
150     glPushAttrib( GL_ENABLE_BIT );
151
152     GLboolean enableTexture = glIsEnabled(GL_TEXTURE_2D);
153     GLboolean enableDepthTest = glIsEnabled(GL_DEPTH_TEST);
154
155     if( !enableTexture )
156       glEnable(GL_TEXTURE_2D);
157     if ( !is2d ) {
158       if ( !enableDepthTest )
159         glEnable(GL_DEPTH_TEST);
160     }
161     else if ( enableDepthTest ) {
162         glDisable(GL_DEPTH_TEST);
163     }
164
165     GLint param;
166     glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &param);
167
168     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 
169     glAlphaFunc(GL_GEQUAL, 0.285f);    
170     glEnable(GL_ALPHA_TEST);   
171     OGLFont_Cache cache = myGeneratedFontCache.Find( id );
172     cache.Font->Render( text );
173
174     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, param);
175
176     if( !enableTexture )
177       glDisable(GL_TEXTURE_2D);
178     if( !enableDepthTest )
179       glDisable(GL_DEPTH_TEST);
180
181     glPopAttrib();
182     glMatrixMode( GL_MODELVIEW );
183     glPopMatrix();
184   }
185
186 }
187
188 void OpenGl_FontMgr::render_text ( const wchar_t* text, const Standard_Boolean is2d )
189 {
190   render_text( myCurrentFontId, text, is2d );
191 }
192
193 const FTFont* OpenGl_FontMgr::fontById (const Standard_Integer id)
194 {
195   return myGeneratedFontCache.IsBound( id ) ? myGeneratedFontCache.Find( id ).Font: NULL;
196 }
197
198 Standard_ShortReal OpenGl_FontMgr::computeWidth( const Standard_Integer id, const wchar_t* text )
199 {
200   if( !myGeneratedFontCache.IsBound( id ) )
201     return 0.f;
202
203   OGLFont_Cache cache = myGeneratedFontCache.Find( id );
204
205   Standard_ShortReal w = cache.Font->Advance( text );
206
207   return w;
208 }
209
210 void OpenGl_FontMgr::setCurrentScale (const Standard_ShortReal xScale,
211                                       const Standard_ShortReal yScale)
212 {
213   myXCurrentScale = xScale;
214   myYCurrentScale = yScale;
215 }
216
217 #include <AlienImage_BMPAlienData.hxx>
218 #include <OSD_File.hxx>
219 #include <OSD_Protection.hxx>
220 #include <Aspect_GenericColorMap.hxx>
221 #include <Image_ColorImage.hxx>
222 #include <Quantity_Color.hxx>
223
224 void dump_texture( int id)
225 {
226   Handle(AlienImage_BMPAlienData) image = new AlienImage_BMPAlienData();
227
228   if (!glIsTexture(id))
229     return;
230
231   unsigned char* pixels = new unsigned char[8192*1024];
232   memset( pixels, 0, 8192*1024 );
233   static int index = 0;
234   index++;
235
236   glBindTexture(GL_TEXTURE_2D, id );
237   glGetTexImage( GL_TEXTURE_2D , 
238     0,
239     GL_ALPHA,
240     GL_UNSIGNED_BYTE,
241     pixels );
242
243   Handle(Image_ColorImage) anImage = new Image_ColorImage( 0, 0, 1024, 8192 );
244
245   Aspect_ColorPixel mark( Quantity_Color (0.,0.5,1., Quantity_TOC_RGB ) ),
246     space( Quantity_Color (1.,1.,1., Quantity_TOC_RGB ) );
247
248   for( int i = 0; i < 1024; i++ ) {
249     for (int j = 0; j < 8192; j++ )
250       if (pixels[i*8192+j]>0) {
251         anImage->SetPixel( anImage->LowerX()+i, 
252           anImage->LowerY()+j,
253           mark );
254       }
255       else {
256         anImage->SetPixel( anImage->LowerX()+i, 
257           anImage->LowerY()+j,
258           space );
259       }
260   }
261
262   image->FromImage( anImage );
263   TCollection_AsciiString name( index );
264   name.Prepend( "D:\\Temp_image" );
265   name += ".bmp";
266   OSD_File file ( name );
267   file.Build( OSD_WriteOnly, OSD_Protection());
268   image->Write(file);
269   file.Close();
270   delete []pixels;
271 }