| 1 | // Created on: 2008-01-20 |
| 2 | // Created by: Alexander A. BORODIN |
| 3 | // Copyright (c) 2008-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 | |
| 20 | #include <Font_FontMgr.ixx> |
| 21 | #ifdef WNT |
| 22 | # include <windows.h> |
| 23 | # include <stdlib.h> |
| 24 | #else //WNT |
| 25 | # include <dirent.h> |
| 26 | # include <X11/Xlib.h> |
| 27 | #endif //WNT |
| 28 | |
| 29 | #include <OSD_Environment.hxx> |
| 30 | #include <NCollection_List.hxx> |
| 31 | #include <TCollection_HAsciiString.hxx> |
| 32 | #include <Standard_Stream.hxx> |
| 33 | |
| 34 | |
| 35 | #ifndef WNT |
| 36 | #include <TCollection_AsciiString.hxx> |
| 37 | |
| 38 | #include <NCollection_DefineList.hxx> |
| 39 | #include <NCollection_List.hxx> |
| 40 | |
| 41 | #include <OSD_Path.hxx> |
| 42 | #include <OSD_FileIterator.hxx> |
| 43 | #include <OSD_DirectoryIterator.hxx> |
| 44 | #include <OSD_File.hxx> |
| 45 | #include <OSD_FileNode.hxx> |
| 46 | #include <OSD_OpenMode.hxx> |
| 47 | #include <OSD_Protection.hxx> |
| 48 | #include <Font_NListOfSystemFont.hxx> |
| 49 | |
| 50 | const Standard_Integer font_service_conf_size = 3; |
| 51 | static Standard_Character font_service_conf[font_service_conf_size][64] = { {"/etc/X11/fs/config"}, |
| 52 | {"/usr/X11R6/lib/X11/fs/config"}, |
| 53 | {"/usr/X11/lib/X11/fs/config"} |
| 54 | }; |
| 55 | |
| 56 | DEFINE_LIST( StringList, NCollection_List, TCollection_HAsciiString ); |
| 57 | |
| 58 | void find_path_with_font_dir( const TCollection_AsciiString& dir,StringList& dirs ) |
| 59 | { |
| 60 | if( !dir.IsEmpty() ) |
| 61 | { |
| 62 | TCollection_AsciiString PathName( dir ); |
| 63 | |
| 64 | Standard_Integer rem = PathName.Length(); |
| 65 | |
| 66 | if ( PathName.SearchFromEnd("/") == rem ) |
| 67 | PathName.Remove( rem, 1 ); |
| 68 | |
| 69 | Standard_Boolean need_to_append = Standard_True; |
| 70 | |
| 71 | StringList::Iterator it( dirs ); |
| 72 | for( ; it.More(); it.Next() ) |
| 73 | { |
| 74 | if ( PathName.IsEqual(it.Value().ToCString()) ) { |
| 75 | need_to_append = Standard_False; |
| 76 | break; |
| 77 | } |
| 78 | } |
| 79 | if ( need_to_append ) |
| 80 | dirs.Append( PathName ); |
| 81 | |
| 82 | OSD_DirectoryIterator osd_dir(PathName,"*"); |
| 83 | while(osd_dir.More()) |
| 84 | { |
| 85 | OSD_Path path_file; |
| 86 | osd_dir.Values().Path( path_file ); |
| 87 | if( path_file.Name().Length() < 1 ) |
| 88 | { |
| 89 | osd_dir.Next(); |
| 90 | continue; |
| 91 | } |
| 92 | |
| 93 | TCollection_AsciiString full_path_name = PathName + "/" + path_file.Name(); |
| 94 | rem = full_path_name.Length(); |
| 95 | if ( full_path_name.SearchFromEnd("/") == rem ) |
| 96 | full_path_name.Remove( rem, 1 ); |
| 97 | find_path_with_font_dir( full_path_name, dirs ); |
| 98 | osd_dir.Next(); |
| 99 | } |
| 100 | } |
| 101 | } |
| 102 | |
| 103 | #endif //WNT |
| 104 | |
| 105 | |
| 106 | Handle(Font_FontMgr) Font_FontMgr::GetInstance() { |
| 107 | |
| 108 | static Handle(Font_FontMgr) _mgr; |
| 109 | if ( _mgr.IsNull() ) |
| 110 | _mgr = new Font_FontMgr(); |
| 111 | |
| 112 | return _mgr; |
| 113 | |
| 114 | } |
| 115 | |
| 116 | Font_FontMgr::Font_FontMgr() { |
| 117 | |
| 118 | InitFontDataBase(); |
| 119 | |
| 120 | } |
| 121 | |
| 122 | void Font_FontMgr::InitFontDataBase() { |
| 123 | |
| 124 | MyListOfFonts.Clear(); |
| 125 | |
| 126 | #ifdef WNT |
| 127 | //detect font directory |
| 128 | |
| 129 | OSD_Environment env("windir"); |
| 130 | TCollection_AsciiString windir_str = env.Value(); |
| 131 | if ( windir_str.IsEmpty() ) |
| 132 | { |
| 133 | return; |
| 134 | } |
| 135 | Handle(TCollection_HAsciiString) HFontDir = new TCollection_HAsciiString( windir_str ); |
| 136 | HFontDir->AssignCat( "\\Fonts\\" ); |
| 137 | #ifdef TRACE |
| 138 | cout << "System font directory: " << HFontDir->ToCString() << "\n"; |
| 139 | #endif TRACE |
| 140 | |
| 141 | //read registry |
| 142 | HKEY fonts_hkey; |
| 143 | if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, |
| 144 | TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"), |
| 145 | 0, |
| 146 | KEY_READ, |
| 147 | &fonts_hkey ) |
| 148 | != ERROR_SUCCESS ) |
| 149 | { |
| 150 | return; |
| 151 | } |
| 152 | Standard_Integer id = 0; |
| 153 | Standard_Character buf_name[100]; |
| 154 | Standard_Byte buf_data[100]; |
| 155 | DWORD size_name = 100, |
| 156 | size_data = 100; |
| 157 | |
| 158 | while ( true ) |
| 159 | { |
| 160 | //detect file name |
| 161 | DWORD type; |
| 162 | size_name = 100, |
| 163 | size_data = 100; |
| 164 | Font_FontAspect aspect; |
| 165 | if( RegEnumValue( fonts_hkey, |
| 166 | id, |
| 167 | buf_name, |
| 168 | &size_name, |
| 169 | NULL, |
| 170 | &type, |
| 171 | buf_data, |
| 172 | &size_data) == ERROR_NO_MORE_ITEMS ) { |
| 173 | break; |
| 174 | } |
| 175 | Handle(TCollection_HAsciiString) fname = |
| 176 | new TCollection_HAsciiString(buf_name); |
| 177 | fname->RightAdjust(); |
| 178 | fname->LeftAdjust(); |
| 179 | //remove construction like (TrueType.... |
| 180 | Standard_Integer anIndexTT = fname->SearchFromEnd( new TCollection_HAsciiString( " (" ) ); |
| 181 | Standard_Boolean aTruncate = Standard_False; |
| 182 | if ( anIndexTT > 1 ) |
| 183 | fname->Trunc( anIndexTT ); |
| 184 | Standard_Integer anIndex = 0; |
| 185 | fname->RightAdjust(); |
| 186 | if ( ( anIndex = fname->SearchFromEnd( new TCollection_HAsciiString("Bold Italic") ) ) > 0 ) { |
| 187 | aTruncate = ( anIndex > 1 ) && ( fname->Value(anIndex - 1 ) == ' ' ); |
| 188 | aspect = Font_FA_BoldItalic; |
| 189 | } else if ( ( anIndex = fname->SearchFromEnd( new TCollection_HAsciiString("Bold") ) ) > 0 ) { |
| 190 | aTruncate = ( anIndex > 1 ) && ( fname->Value(anIndex - 1 ) == ' ' ); |
| 191 | aspect = Font_FA_Bold; |
| 192 | } else if ( ( anIndex = fname->SearchFromEnd( new TCollection_HAsciiString("Italic") ) ) > 0 ) { |
| 193 | aTruncate = ( anIndex > 1 ) && ( fname->Value(anIndex - 1 ) == ' ' ); |
| 194 | aspect = Font_FA_Italic; |
| 195 | } else { |
| 196 | aspect = Font_FA_Regular; |
| 197 | } |
| 198 | if( aTruncate ) |
| 199 | fname->Trunc( anIndex - 1 ); |
| 200 | fname->RightAdjust(); |
| 201 | Handle(TCollection_HAsciiString) file_path = |
| 202 | new TCollection_HAsciiString( (Standard_Character*)buf_data ); |
| 203 | if ( strchr( (Standard_Character*)buf_data, '\\' ) == NULL ) { |
| 204 | file_path->Insert( 1, HFontDir ); |
| 205 | } |
| 206 | |
| 207 | if( ( ( file_path->Search(".ttf") > 0 ) || ( file_path->Search(".TTF") > 0 ) || |
| 208 | ( file_path->Search(".otf") > 0 ) || ( file_path->Search(".OTF") > 0 ) || |
| 209 | ( file_path->Search(".ttc") > 0 ) || ( file_path->Search(".TTC") > 0 ) ) ){ |
| 210 | MyListOfFonts.Append( new Font_SystemFont( fname, aspect, file_path ) ); |
| 211 | #ifdef TRACE |
| 212 | cout << "Adding font...\n" |
| 213 | << " font name: " << fname->ToCString() << "\n" |
| 214 | << " font file: " << file_path->ToCString() << "\n" |
| 215 | << " font aspect: "; |
| 216 | switch( aspect ) { |
| 217 | case Font_FA_Bold: |
| 218 | cout << "Font_FA_Bold\n"; |
| 219 | break; |
| 220 | case Font_FA_BoldItalic: |
| 221 | cout << "Font_FA_BoldItalic\n"; |
| 222 | break; |
| 223 | case Font_FA_Italic: |
| 224 | cout << "Font_FA_Italic\n"; |
| 225 | break; |
| 226 | default: |
| 227 | cout << "Font_FA_Regular\n"; |
| 228 | break; |
| 229 | } |
| 230 | #endif |
| 231 | } |
| 232 | id++; |
| 233 | } |
| 234 | //close registry |
| 235 | RegCloseKey( fonts_hkey ); |
| 236 | #endif //WNT |
| 237 | |
| 238 | #ifndef WNT |
| 239 | StringList dirs; |
| 240 | Handle(TCollection_HAsciiString) str = new TCollection_HAsciiString; |
| 241 | Display * disp = XOpenDisplay("localhost:0.0"); |
| 242 | |
| 243 | if (!disp) |
| 244 | { |
| 245 | // let the X server find the available connection |
| 246 | disp = XOpenDisplay(":0.0"); |
| 247 | if (!disp) |
| 248 | { |
| 249 | cout << "Display is NULL!" << endl; |
| 250 | return ; |
| 251 | } |
| 252 | } |
| 253 | |
| 254 | Standard_Integer npaths = 0; |
| 255 | |
| 256 | Standard_Character** fontpath = XGetFontPath(disp, &npaths); |
| 257 | #ifdef TRACE |
| 258 | cout << "NPATHS = " << npaths << endl ; |
| 259 | #endif |
| 260 | for (Standard_Integer i = 0; i < npaths; i++ ) |
| 261 | { |
| 262 | #ifdef TRACE |
| 263 | cout << "Font Path: " << fontpath[i] << endl; |
| 264 | #endif |
| 265 | if ( fontpath[i][0] == '/' ) { |
| 266 | TCollection_AsciiString aFontPath( fontpath[i] ); |
| 267 | find_path_with_font_dir( aFontPath, dirs ); |
| 268 | } |
| 269 | else |
| 270 | { |
| 271 | TCollection_AsciiString aFontPath( fontpath[i] ); |
| 272 | TCollection_AsciiString aCutFontPath; |
| 273 | Standard_Integer location = -1 ; |
| 274 | location = aFontPath.Location( "/",1,aFontPath.Length() ); |
| 275 | if( location > 0 ) |
| 276 | aCutFontPath.AssignCat( aFontPath.SubString(location, aFontPath.Length() ) ); |
| 277 | find_path_with_font_dir( aCutFontPath, dirs ); |
| 278 | } |
| 279 | } |
| 280 | XFreeFontPath(fontpath); |
| 281 | |
| 282 | |
| 283 | OSD_OpenMode aMode = OSD_ReadOnly; |
| 284 | OSD_Protection aProtect( OSD_R, OSD_R, OSD_R, OSD_R ); |
| 285 | |
| 286 | for( Standard_Integer j = 0 ; j < font_service_conf_size; j++ ) |
| 287 | { |
| 288 | TCollection_AsciiString fileOfFontServiceName( font_service_conf[j] ); |
| 289 | OSD_File aFile( fileOfFontServiceName ); |
| 290 | |
| 291 | if( aFile.Exists() ) |
| 292 | aFile.Open( aMode, aProtect ); |
| 293 | |
| 294 | if( aFile.IsOpen() )//font service |
| 295 | { |
| 296 | Standard_Integer aNByte = 256; |
| 297 | Standard_Integer aNbyteRead; |
| 298 | TCollection_AsciiString aStr( aNByte );//read string with information |
| 299 | TCollection_AsciiString aStrCut( aNByte );//cut of string |
| 300 | TCollection_AsciiString endStr;//cutting string |
| 301 | |
| 302 | Standard_Boolean read_dirs = Standard_False; |
| 303 | Standard_Integer location =- 1; //disposition of necessary literals |
| 304 | Standard_Integer begin =- 1; //first left entry in string |
| 305 | Standard_Integer end =- 1; //first right entry in string |
| 306 | while( !aFile.IsAtEnd() ) |
| 307 | { |
| 308 | aFile.ReadLine( aStr, aNByte, aNbyteRead );//reading 1 lines(256 bytes) |
| 309 | location = aStr.Location( "catalogue = ", 1, aStr.Length() ); |
| 310 | if(location == 0) |
| 311 | location = aStr.Location( "catalogue=", 1, aStr.Length() ); |
| 312 | if(location == 0) |
| 313 | location = aStr.Location( "catalogue= ", 1, aStr.Length() ); |
| 314 | if(location == 0) |
| 315 | location = aStr.Location( "catalogue = ", 1, aStr.Length() ); |
| 316 | if( location > 0 ) |
| 317 | { |
| 318 | #ifdef TRACE |
| 319 | cout << " Font config find!!" << endl; |
| 320 | #endif |
| 321 | read_dirs = Standard_True; |
| 322 | } |
| 323 | |
| 324 | if( read_dirs ) |
| 325 | { |
| 326 | begin = aStr.Location( "/", 1, aStr.Length() );//begin of path name |
| 327 | end = aStr.Location( ":", 1, aStr.Length() );//end of path name |
| 328 | if( end < 1 ) |
| 329 | end = aStr.Location( ",", 1, aStr.Length() );//also end of path name |
| 330 | end -= 1; |
| 331 | if( begin > 0 && end > 0 ) |
| 332 | { |
| 333 | if( ( end - begin ) > 0 ) |
| 334 | endStr.AssignCat( aStr.SubString ( begin, end ) );//cutting necessary literals for string |
| 335 | dirs.Append( TCollection_HAsciiString ( endStr ) ); |
| 336 | endStr.Clear(); |
| 337 | } |
| 338 | else |
| 339 | if( begin > 0 && end == -1 ) |
| 340 | { |
| 341 | //if end of string don't have "," or ":" |
| 342 | //it is possible last sentence in block of word |
| 343 | endStr.AssignCat( aStr.SubString( begin, aStr.Length() - 1 ) ); |
| 344 | dirs.Append( TCollection_HAsciiString( endStr ) ); |
| 345 | endStr.Clear(); |
| 346 | } |
| 347 | } |
| 348 | |
| 349 | } |
| 350 | aFile.Close(); |
| 351 | } |
| 352 | } |
| 353 | |
| 354 | if( dirs.Size() > 0 ) |
| 355 | { |
| 356 | //if dirs list contains elements |
| 357 | OSD_OpenMode aModeRead = OSD_ReadOnly; |
| 358 | OSD_Protection aProtectRead( OSD_R, OSD_R , OSD_R , OSD_R ); |
| 359 | |
| 360 | TCollection_AsciiString fileFontsDir; |
| 361 | StringList::Iterator it( dirs ); |
| 362 | for( ; it.More(); it.Next() ) |
| 363 | { |
| 364 | fileFontsDir.AssignCat( it.Value().ToCString() ); |
| 365 | fileFontsDir.AssignCat( "/fonts.dir" );//append file name in path way |
| 366 | |
| 367 | OSD_File readFile( fileFontsDir ); |
| 368 | readFile.Open( aModeRead, aProtectRead ); |
| 369 | |
| 370 | Standard_Integer aNbyteRead, aNByte = 256; |
| 371 | if( readFile.IsOpen ( ) ) |
| 372 | { |
| 373 | TCollection_AsciiString aLine( aNByte ); |
| 374 | Standard_Integer countOfString = 0 ; |
| 375 | while( ! readFile.IsAtEnd() )//return true if EOF |
| 376 | { |
| 377 | if( countOfString > 1 ) |
| 378 | { |
| 379 | readFile.ReadLine( aLine , aNByte , aNbyteRead ); |
| 380 | if( ( ( aLine.Search(".pfa") > 0 ) || ( aLine.Search(".PFA") > 0 ) || |
| 381 | ( aLine.Search(".pfb") > 0 ) || ( aLine.Search(".PFB") > 0 ) || |
| 382 | ( aLine.Search(".ttf") > 0 ) || ( aLine.Search(".TTF") > 0 ) || |
| 383 | ( aLine.Search(".otf") > 0 ) || ( aLine.Search(".OTF") > 0 ) || |
| 384 | ( aLine.Search(".ttc") > 0 ) || ( aLine.Search(".TTC") > 0 ) ) |
| 385 | && ( aLine.Search( "iso8859-1\n" ) > 0 ) ) |
| 386 | { |
| 387 | |
| 388 | // In current implementation use fonts with ISO-8859-1 coding page. |
| 389 | // OCCT not give to manage coding page by means of programm interface. |
| 390 | // TODO: make high level interface for |
| 391 | // choosing necessary coding page. |
| 392 | TCollection_AsciiString aXLFD; |
| 393 | Standard_Integer leftXLFD = aLine.SearchFromEnd(" "); |
| 394 | Standard_Integer rightXLFD = aLine.Length(); |
| 395 | if( leftXLFD && rightXLFD ) |
| 396 | aXLFD.AssignCat(aLine.SubString( leftXLFD + 1, rightXLFD ) ); |
| 397 | |
| 398 | TCollection_AsciiString aPath; |
| 399 | TCollection_AsciiString aTemp( it.Value().ToCString() ); |
| 400 | if ( aTemp.SearchFromEnd("/") == aTemp.Length() ) |
| 401 | { |
| 402 | //this branch intend to SUN |
| 403 | aPath.AssignCat( aTemp.ToCString() ); |
| 404 | aPath.AssignCat( aLine.Token( " ", 1 ) ); |
| 405 | } |
| 406 | else { |
| 407 | //this branch intend to Linux |
| 408 | aPath.AssignCat( aTemp.ToCString( ) ); |
| 409 | aPath.AssignCat( "/" ); |
| 410 | aPath.AssignCat( aLine.Token( " ", 1 ) ); |
| 411 | } |
| 412 | MyListOfFonts.Append( new Font_SystemFont( new TCollection_HAsciiString( aXLFD ), |
| 413 | new TCollection_HAsciiString( aPath ) ) ); |
| 414 | } |
| 415 | |
| 416 | } |
| 417 | else |
| 418 | readFile.ReadLine( aLine, aNByte, aNbyteRead ); |
| 419 | countOfString++; |
| 420 | } |
| 421 | readFile.Close(); |
| 422 | } |
| 423 | fileFontsDir.Clear(); |
| 424 | } |
| 425 | } |
| 426 | #endif |
| 427 | } |
| 428 | |
| 429 | Font_NListOfSystemFont Font_FontMgr::GetAvalableFonts() const |
| 430 | { |
| 431 | return MyListOfFonts; |
| 432 | } |
| 433 | |
| 434 | |