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