d49a6764a8bd25d5f824dd9ad646063227f5f29c
[occt.git] / src / Font / Font_FontMgr.cxx
1 // Created on: 2008-01-20
2 // Created by: Alexander A. BORODIN
3 // Copyright (c) 2008-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16
17 #include <Font_FontMgr.hxx>
18 #include <Font_FTLibrary.hxx>
19 #include <Font_SystemFont.hxx>
20 #include <NCollection_List.hxx>
21 #include <NCollection_Map.hxx>
22 #include <OSD_Environment.hxx>
23 #include <Standard_Stream.hxx>
24 #include <Standard_Type.hxx>
25 #include <TCollection_HAsciiString.hxx>
26
27 #include <ft2build.h>
28 #include FT_FREETYPE_H
29 IMPLEMENT_STANDARD_RTTIEXT(Font_FontMgr,Standard_Transient)
30
31 struct Font_FontMgr_FontAliasMapNode
32 {
33   const char *    EnumName;
34   const char *    FontName;
35   Font_FontAspect FontAspect;
36 };
37
38 static const Font_FontMgr_FontAliasMapNode Font_FontMgr_MapOfFontsAliases[] =
39 {
40
41 #if defined(_WIN32) || defined(__APPLE__)
42
43   { "Courier"                  , "Courier New"    , Font_FA_Regular },
44   { "Times-Roman"              , "Times New Roman", Font_FA_Regular  },
45   { "Times-Bold"               , "Times New Roman", Font_FA_Bold },
46   { "Times-Italic"             , "Times New Roman", Font_FA_Italic  },
47   { "Times-BoldItalic"         , "Times New Roman", Font_FA_BoldItalic  },
48   { "ZapfChancery-MediumItalic", "Script"         , Font_FA_Regular  },
49   { "Symbol"                   , "Symbol"         , Font_FA_Regular  },
50   { "ZapfDingbats"             , "WingDings"      , Font_FA_Regular  },
51   { "Rock"                     , "Arial"          , Font_FA_Regular  },
52   { "Iris"                     , "Lucida Console" , Font_FA_Regular  },
53   { "NSimSun"                  , "SimSun"         , Font_FA_Regular  }
54
55 #elif defined(__ANDROID__)
56
57   { "Courier"                  , "Droid Sans Mono", Font_FA_Regular },
58   { "Times-Roman"              , "Droid Serif"    , Font_FA_Regular  },
59   { "Times-Bold"               , "Droid Serif"    , Font_FA_Bold },
60   { "Times-Italic"             , "Droid Serif"    , Font_FA_Italic  },
61   { "Times-BoldItalic"         , "Droid Serif"    , Font_FA_BoldItalic  },
62   { "Arial"                    , "Roboto"         , Font_FA_Regular  },
63
64 #else   //X11
65
66   { "Courier"                  , "Courier"      , Font_FA_Regular },
67   { "Times-Roman"              , "Times"        , Font_FA_Regular  },
68   { "Times-Bold"               , "Times"        , Font_FA_Bold },
69   { "Times-Italic"             , "Times"        , Font_FA_Italic  },
70   { "Times-BoldItalic"         , "Times"        , Font_FA_BoldItalic  },
71   { "Arial"                    , "Helvetica"    , Font_FA_Regular  },
72   { "ZapfChancery-MediumItalic", "-adobe-itc zapf chancery-medium-i-normal--*-*-*-*-*-*-iso8859-1"              , Font_FA_Regular  },
73   { "Symbol"                   , "-adobe-symbol-medium-r-normal--*-*-*-*-*-*-adobe-fontspecific"                , Font_FA_Regular  },
74   { "ZapfDingbats"             , "-adobe-itc zapf dingbats-medium-r-normal--*-*-*-*-*-*-adobe-fontspecific"     , Font_FA_Regular  },
75   { "Rock"                     , "-sgi-rock-medium-r-normal--*-*-*-*-p-*-iso8859-1"                             , Font_FA_Regular  },
76   { "Iris"                     , "--iris-medium-r-normal--*-*-*-*-m-*-iso8859-1"                                , Font_FA_Regular  }
77 #endif
78
79 };
80
81 #define NUM_FONT_ENTRIES (int)(sizeof(Font_FontMgr_MapOfFontsAliases)/sizeof(Font_FontMgr_FontAliasMapNode))
82
83 #if defined(_WIN32)
84
85   #include <windows.h>
86   #include <stdlib.h>
87
88   #ifdef _MSC_VER
89     #pragma comment (lib, "freetype.lib")
90   #endif
91
92   namespace
93   {
94
95     // list of supported extensions
96     static Standard_CString Font_FontMgr_Extensions[] =
97     {
98       "ttf",
99       "otf",
100       "ttc",
101       NULL
102     };
103
104   };
105
106 #else
107
108   #include <OSD_DirectoryIterator.hxx>
109   #include <OSD_FileIterator.hxx>
110   #include <OSD_Path.hxx>
111   #include <OSD_File.hxx>
112   #include <OSD_OpenMode.hxx>
113   #include <OSD_Protection.hxx>
114
115   namespace
116   {
117
118     // list of supported extensions
119     static Standard_CString Font_FontMgr_Extensions[] =
120     {
121       "ttf",
122       "otf",
123       "ttc",
124       "pfa",
125       "pfb",
126     #ifdef __APPLE__
127       // Datafork TrueType (OS X), obsolete
128       //"dfont",
129     #endif
130       NULL
131     };
132
133   #if !defined(__ANDROID__) && !defined(__APPLE__)
134     // X11 configuration file in plain text format (obsolete - doesn't exists in modern distributives)
135     static Standard_CString myFontServiceConf[] = {"/etc/X11/fs/config",
136                                                    "/usr/X11R6/lib/X11/fs/config",
137                                                    "/usr/X11/lib/X11/fs/config",
138                                                    NULL
139                                                   };
140   #endif
141
142   #ifdef __APPLE__
143     // default fonts paths in Mac OS X
144     static Standard_CString myDefaultFontsDirs[] = {"/System/Library/Fonts",
145                                                     "/Library/Fonts",
146                                                     NULL
147                                                    };
148   #else
149     // default fonts paths in most Unix systems (Linux and others)
150     static Standard_CString myDefaultFontsDirs[] = {"/system/fonts",         // Android
151                                                     "/usr/share/fonts",
152                                                     "/usr/local/share/fonts",
153                                                     NULL
154                                                    };
155   #endif
156
157     static void addDirsRecursively (const OSD_Path&                           thePath,
158                                     NCollection_Map<TCollection_AsciiString>& theDirsMap)
159     {
160       TCollection_AsciiString aDirName;
161       thePath.SystemName (aDirName);
162       if (!theDirsMap.Add (aDirName))
163       {
164         return;
165       }
166
167       for (OSD_DirectoryIterator aDirIterator (thePath, "*"); aDirIterator.More(); aDirIterator.Next())
168       {
169         OSD_Path aChildDirPath;
170         aDirIterator.Values().Path (aChildDirPath);
171
172         TCollection_AsciiString aChildDirName;
173         aChildDirPath.SystemName (aChildDirName);
174         if (!aChildDirName.IsEqual (".") && !aChildDirName.IsEqual (".."))
175         {
176           aChildDirName = aDirName + "/" + aChildDirName;
177           OSD_Path aPath (aChildDirName);
178           addDirsRecursively (aPath, theDirsMap);
179         }
180       }
181     }
182
183   } // anonymous namespace
184
185 #endif
186
187 // =======================================================================
188 // function : checkFont
189 // purpose  :
190 // =======================================================================
191 static Handle(Font_SystemFont) checkFont (const Handle(Font_FTLibrary)& theFTLib,
192                                           const Standard_CString        theFontPath)
193 {
194   FT_Face aFontFace;
195   FT_Error aFaceError = FT_New_Face (theFTLib->Instance(), theFontPath, 0, &aFontFace);
196   if (aFaceError != FT_Err_Ok)
197   {
198     return NULL;
199   }
200
201   Font_FontAspect anAspect = Font_FA_Regular;
202   if (aFontFace->style_flags == (FT_STYLE_FLAG_ITALIC | FT_STYLE_FLAG_BOLD))
203   {
204     anAspect = Font_FA_BoldItalic;
205   }
206   else if (aFontFace->style_flags == FT_STYLE_FLAG_ITALIC)
207   {
208     anAspect = Font_FA_Italic;
209   }
210   else if (aFontFace->style_flags == FT_STYLE_FLAG_BOLD)
211   {
212     anAspect = Font_FA_Bold;
213   }
214
215   Handle(Font_SystemFont) aResult;
216   if (aFontFace->family_name != NULL                           // skip broken fonts (error in FreeType?)
217    && FT_Select_Charmap (aFontFace, ft_encoding_unicode) == 0) // Font_FTFont supports only UNICODE fonts
218   {
219     Handle(TCollection_HAsciiString) aFontName = new TCollection_HAsciiString (aFontFace->family_name);
220     Handle(TCollection_HAsciiString) aFontPath = new TCollection_HAsciiString (theFontPath);
221     aResult = new Font_SystemFont (aFontName, anAspect, aFontPath);
222     // automatically identify some known single-line fonts
223     aResult->SetSingleStrokeFont (aFontName->String().StartsWith ("OLF "));
224   }
225
226   FT_Done_Face (aFontFace);
227
228   return aResult;
229 }
230
231 // =======================================================================
232 // function : GetInstance
233 // purpose  :
234 // =======================================================================
235 Handle(Font_FontMgr) Font_FontMgr::GetInstance()
236 {
237   static Handle(Font_FontMgr) _mgr;
238   if (_mgr.IsNull())
239   {
240     _mgr = new Font_FontMgr();
241   }
242
243   return _mgr;
244 }
245
246 // =======================================================================
247 // function : Font_FontMgr
248 // purpose  :
249 // =======================================================================
250 Font_FontMgr::Font_FontMgr()
251 {
252   InitFontDataBase();
253 }
254
255 // =======================================================================
256 // function : CheckFont
257 // purpose  :
258 // =======================================================================
259 Handle(Font_SystemFont) Font_FontMgr::CheckFont (Standard_CString theFontPath) const
260 {
261   Handle(Font_FTLibrary) aFtLibrary = new Font_FTLibrary();
262   return checkFont (aFtLibrary, theFontPath);
263 }
264
265 // =======================================================================
266 // function : RegisterFont
267 // purpose  :
268 // =======================================================================
269 Standard_Boolean Font_FontMgr::RegisterFont (const Handle(Font_SystemFont)& theFont,
270                                              const Standard_Boolean         theToOverride)
271 {
272   if (theFont.IsNull())
273   {
274     return Standard_False;
275   }
276
277   for (Font_NListOfSystemFont::Iterator aFontIter (myListOfFonts);
278        aFontIter.More(); aFontIter.Next())
279   {
280     if (!aFontIter.Value()->FontName()->IsSameString (theFont->FontName(), Standard_False))
281     {
282       continue;
283     }
284
285     if (theFont->FontAspect() != Font_FA_Undefined
286      && aFontIter.Value()->FontAspect() != theFont->FontAspect())
287     {
288       continue;
289     }
290
291     if (theFont->FontHeight() == -1 || aFontIter.Value()->FontHeight() == -1
292      || theFont->FontHeight() ==       aFontIter.Value()->FontHeight())
293     {
294       if (theFont->FontPath()->String() == aFontIter.Value()->FontPath()->String())
295       {
296         return Standard_True;
297       }
298       else if (theToOverride)
299       {
300         myListOfFonts.Remove (aFontIter);
301       }
302       else
303       {
304         return Standard_False;
305       }
306     }
307   }
308
309   myListOfFonts.Append (theFont);
310   return Standard_True;
311 }
312
313 // =======================================================================
314 // function : InitFontDataBase
315 // purpose  :
316 // =======================================================================
317 void Font_FontMgr::InitFontDataBase()
318 {
319   myListOfFonts.Clear();
320   Handle(Font_FTLibrary) aFtLibrary;
321
322 #if defined(OCCT_UWP)
323   // system font files are not accessible
324   (void )aFtLibrary;
325 #elif defined(_WIN32)
326
327   // font directory is placed in "C:\Windows\Fonts\"
328   UINT aStrLength = GetSystemWindowsDirectoryA (NULL, 0);
329   if (aStrLength == 0)
330   {
331     return;
332   }
333
334   char* aWinDir = new char[aStrLength];
335   GetSystemWindowsDirectoryA (aWinDir, aStrLength);
336   Handle(TCollection_HAsciiString) aFontsDir = new TCollection_HAsciiString (aWinDir);
337   aFontsDir->AssignCat ("\\Fonts\\");
338   delete[] aWinDir;
339
340   // read fonts list from registry
341   HKEY aFontsKey;
342   if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts",
343                      0, KEY_READ, &aFontsKey) != ERROR_SUCCESS)
344   {
345     return;
346   }
347
348   NCollection_Map<TCollection_AsciiString> aSupportedExtensions;
349   for (Standard_Integer anIter = 0; Font_FontMgr_Extensions[anIter] != NULL; ++anIter)
350   {
351     Standard_CString anExt = Font_FontMgr_Extensions[anIter];
352     aSupportedExtensions.Add (TCollection_AsciiString (anExt));
353   }
354
355   aFtLibrary = new Font_FTLibrary();
356   static const DWORD aBufferSize = 256;
357   char aNameBuff[aBufferSize];
358   char aPathBuff[aBufferSize];
359   DWORD aNameSize = aBufferSize;
360   DWORD aPathSize = aBufferSize;
361   for (DWORD anIter = 0;
362        RegEnumValueA (aFontsKey, anIter,
363                       aNameBuff, &aNameSize, NULL, NULL,
364                       (LPBYTE )aPathBuff, &aPathSize) != ERROR_NO_MORE_ITEMS;
365       ++anIter, aNameSize = aBufferSize, aPathSize = aBufferSize)
366   {
367     aPathBuff[(aPathSize < aBufferSize) ? aPathSize : (aBufferSize - 1)] = '\0'; // ensure string is NULL-terminated
368
369     Handle(TCollection_HAsciiString) aFontName = new TCollection_HAsciiString (aNameBuff);
370     Handle(TCollection_HAsciiString) aFontPath = new TCollection_HAsciiString (aPathBuff);
371     if (aFontPath->Search ("\\") == -1)
372     {
373       aFontPath->Insert (1, aFontsDir); // make absolute path
374     }
375
376     // check file extension is in list of supported
377     const Standard_Integer anExtensionPosition = aFontPath->SearchFromEnd (".") + 1;
378     if (anExtensionPosition > 0 && anExtensionPosition < aFontPath->Length())
379     {
380       Handle(TCollection_HAsciiString) aFontExtension = aFontPath->SubString (anExtensionPosition, aFontPath->Length());
381       aFontExtension->LowerCase();
382       if (aSupportedExtensions.Contains (aFontExtension->String()))
383       {
384         Handle(Font_SystemFont) aNewFont = checkFont (aFtLibrary, aFontPath->ToCString());
385         if (!aNewFont.IsNull())
386         {
387           myListOfFonts.Append (aNewFont);
388         }
389       }
390     }
391   }
392
393   // close registry key
394   RegCloseKey (aFontsKey);
395
396 #else
397
398   NCollection_Map<TCollection_AsciiString> aMapOfFontsDirs;
399 #if !defined(__ANDROID__) && !defined(__APPLE__)
400   const OSD_Protection aProtectRead (OSD_R, OSD_R, OSD_R, OSD_R);
401
402   // read fonts directories from font service config file (obsolete)
403   for (Standard_Integer anIter = 0; myFontServiceConf[anIter] != NULL; ++anIter)
404   {
405     const TCollection_AsciiString aFileOfFontsPath (myFontServiceConf[anIter]);
406     OSD_File aFile (aFileOfFontsPath);
407     if (!aFile.Exists())
408     {
409       continue;
410     }
411
412     aFile.Open (OSD_ReadOnly, aProtectRead);
413     if (!aFile.IsOpen())
414     {
415       continue;
416     }
417
418     Standard_Integer aNByte = 256;
419     Standard_Integer aNbyteRead;
420     TCollection_AsciiString aStr; // read string with information
421     while (!aFile.IsAtEnd())
422     {
423       Standard_Integer aLocation = -1;
424       Standard_Integer aPathLocation = -1;
425
426       aFile.ReadLine (aStr, aNByte, aNbyteRead); // reading 1 line (256 bytes)
427       aLocation = aStr.Search ("catalogue=");
428       if (aLocation < 0)
429       {
430         aLocation = aStr.Search ("catalogue =");
431       }
432
433       aPathLocation = aStr.Search ("/");
434       if (aLocation > 0 && aPathLocation > 0)
435       {
436         aStr = aStr.Split (aPathLocation - 1);
437         TCollection_AsciiString aFontPath;
438         Standard_Integer aPathNumber = 1;
439         do
440         {
441           // Getting directory paths, which can be splitted by "," or ":"
442           aFontPath = aStr.Token (":,", aPathNumber);
443           aFontPath.RightAdjust();
444           if (!aFontPath.IsEmpty())
445           {
446             OSD_Path aPath(aFontPath);
447             addDirsRecursively (aPath, aMapOfFontsDirs);
448           }
449           aPathNumber++;
450         }
451         while (!aFontPath.IsEmpty());
452       }
453     }
454     aFile.Close();
455   }
456 #endif
457
458   // append default directories
459   for (Standard_Integer anIter = 0; myDefaultFontsDirs[anIter] != NULL; ++anIter)
460   {
461     Standard_CString anItem = myDefaultFontsDirs[anIter];
462     TCollection_AsciiString aPathStr (anItem);
463     OSD_Path aPath (aPathStr);
464     addDirsRecursively (aPath, aMapOfFontsDirs);
465   }
466
467   NCollection_Map<TCollection_AsciiString> aSupportedExtensions;
468   for (Standard_Integer anIter = 0; Font_FontMgr_Extensions[anIter] != NULL; ++anIter)
469   {
470     Standard_CString anExt = Font_FontMgr_Extensions[anIter];
471     aSupportedExtensions.Add (TCollection_AsciiString (anExt));
472   }
473
474   aFtLibrary = new Font_FTLibrary();
475   for (NCollection_Map<TCollection_AsciiString>::Iterator anIter (aMapOfFontsDirs);
476        anIter.More(); anIter.Next())
477   {
478   #if defined(__ANDROID__) || defined(__APPLE__)
479     OSD_Path aFolderPath (anIter.Value());
480     for (OSD_FileIterator aFileIter (aFolderPath, "*"); aFileIter.More(); aFileIter.Next())
481     {
482       OSD_Path aFontFilePath;
483       aFileIter.Values().Path (aFontFilePath);
484
485       TCollection_AsciiString aFontFileName;
486       aFontFilePath.SystemName (aFontFileName);
487       aFontFileName = anIter.Value() + "/" + aFontFileName;
488
489       Handle(Font_SystemFont) aNewFont = checkFont (aFtLibrary, aFontFileName.ToCString());
490       if (!aNewFont.IsNull())
491       {
492         myListOfFonts.Append (aNewFont);
493       }
494     }
495   #else
496     OSD_File aReadFile (anIter.Value() + "/fonts.dir");
497     if (!aReadFile.Exists())
498     {
499       continue; // invalid fonts directory
500     }
501
502     aReadFile.Open (OSD_ReadOnly, aProtectRead);
503     if (!aReadFile.IsOpen())
504     {
505       continue; // invalid fonts directory
506     }
507
508     Standard_Integer aNbyteRead, aNByte = 256;
509     TCollection_AsciiString aLine (aNByte);
510     Standard_Boolean isFirstLine = Standard_True;
511     const TCollection_AsciiString anEncoding ("iso8859-1\n");
512     while (!aReadFile.IsAtEnd())
513     {
514       aReadFile.ReadLine (aLine, aNByte, aNbyteRead);
515       if (isFirstLine)
516       {
517         // first line contains the number of fonts in this file
518         // just ignoring it...
519         isFirstLine = Standard_False;
520         continue;
521       }
522
523       Standard_Integer anExtensionPosition = aLine.Search (".") + 1;
524       if (anExtensionPosition == 0)
525       {
526         continue; // can't find extension position in the font description
527       }
528
529       Standard_Integer anEndOfFileName = aLine.Location (" ", anExtensionPosition, aLine.Length()) - 1;
530       if (anEndOfFileName < 0 || anEndOfFileName < anExtensionPosition)
531       {
532         continue; // font description have empty extension
533       }
534
535       TCollection_AsciiString aFontExtension = aLine.SubString (anExtensionPosition, anEndOfFileName);
536       aFontExtension.LowerCase();
537       if (aSupportedExtensions.Contains (aFontExtension) && (aLine.Search (anEncoding) > 0))
538       {
539         // In current implementation use fonts with ISO-8859-1 coding page.
540         // OCCT not give to manage coding page by means of programm interface.
541         // TODO: make high level interface for choosing necessary coding page.
542         Handle(TCollection_HAsciiString) aXLFD =
543           new TCollection_HAsciiString (aLine.SubString (anEndOfFileName + 2, aLine.Length()));
544         Handle(TCollection_HAsciiString) aFontPath =
545           new TCollection_HAsciiString (anIter.Value().ToCString());
546         if (aFontPath->SearchFromEnd ("/") != aFontPath->Length())
547         {
548           aFontPath->AssignCat ("/");
549         }
550         Handle(TCollection_HAsciiString) aFontFileName =
551         new TCollection_HAsciiString (aLine.SubString (1, anEndOfFileName));
552         aFontPath->AssignCat (aFontFileName);
553
554         Handle(Font_SystemFont) aNewFontFromXLFD = new Font_SystemFont (aXLFD, aFontPath);
555         Handle(Font_SystemFont) aNewFont = checkFont (aFtLibrary, aFontPath->ToCString());
556
557         if (aNewFontFromXLFD->IsValid() && !aNewFont.IsNull() &&
558            !aNewFont->IsEqual (aNewFontFromXLFD))
559         {
560           myListOfFonts.Append (aNewFont);
561           myListOfFonts.Append (aNewFontFromXLFD);
562         }
563         else if (!aNewFont.IsNull())
564         {
565           myListOfFonts.Append (aNewFont);
566         }
567         else if (aNewFontFromXLFD->IsValid())
568         {
569           myListOfFonts.Append (aNewFontFromXLFD);
570         }
571       }
572     }
573     aReadFile.Close();
574   #endif
575   }
576 #endif
577 }
578
579 // =======================================================================
580 // function : GetAvailableFonts
581 // purpose  :
582 // =======================================================================
583 const Font_NListOfSystemFont& Font_FontMgr::GetAvailableFonts() const
584 {
585   return myListOfFonts;
586 }
587
588 // =======================================================================
589 // function : GetAvailableFontsNames
590 // purpose  :
591 // =======================================================================
592 void Font_FontMgr::GetAvailableFontsNames (TColStd_SequenceOfHAsciiString& theFontsNames) const
593 {
594   theFontsNames.Clear();
595   for (Font_NListOfSystemFont::Iterator anIter(myListOfFonts); anIter.More(); anIter.Next())
596   {
597     theFontsNames.Append (anIter.Value()->FontName());
598   }
599 }
600
601 // =======================================================================
602 // function : GetFont
603 // purpose  :
604 // =======================================================================
605 Handle(Font_SystemFont) Font_FontMgr::GetFont (const Handle(TCollection_HAsciiString)& theFontName,
606                                                const Font_FontAspect  theFontAspect,
607                                                const Standard_Integer theFontSize) const
608 {
609   if ( (theFontSize < 2 && theFontSize != -1) || theFontName.IsNull())
610   {
611     return NULL;
612   }
613
614   for (Font_NListOfSystemFont::Iterator aFontsIterator (myListOfFonts);
615        aFontsIterator.More(); aFontsIterator.Next())
616   {
617     if (!theFontName->IsEmpty() && !aFontsIterator.Value()->FontName()->IsSameString (theFontName, Standard_False))
618     {
619       continue;
620     }
621
622     if (theFontAspect != Font_FA_Undefined && aFontsIterator.Value()->FontAspect() != theFontAspect)
623     {
624       continue;
625     }
626
627     if (theFontSize == -1 || aFontsIterator.Value()->FontHeight() == -1 ||
628         theFontSize == aFontsIterator.Value()->FontHeight())
629     {
630       return aFontsIterator.Value();
631     }
632   }
633
634   return NULL;
635 }
636
637 // =======================================================================
638 // function : FindFont
639 // purpose  :
640 // =======================================================================
641 Handle(Font_SystemFont) Font_FontMgr::FindFont (const Handle(TCollection_HAsciiString)& theFontName,
642                                                 const Font_FontAspect  theFontAspect,
643                                                 const Standard_Integer theFontSize) const
644 {
645   Handle(TCollection_HAsciiString) aFontName   = theFontName;
646   Font_FontAspect                  aFontAspect = theFontAspect;
647   Standard_Integer                 aFontSize   = theFontSize;
648
649   Handle(Font_SystemFont) aFont = GetFont (aFontName, aFontAspect, aFontSize);
650   if (!aFont.IsNull())
651   {
652     return aFont;
653   }
654
655   // Trying to use font names mapping
656   for (Standard_Integer anIter = 0; anIter < NUM_FONT_ENTRIES; ++anIter)
657   {
658     Handle(TCollection_HAsciiString) aFontAlias =
659       new TCollection_HAsciiString (Font_FontMgr_MapOfFontsAliases[anIter].EnumName);
660
661     if (aFontAlias->IsSameString (aFontName, Standard_False))
662     {
663       aFontName = new TCollection_HAsciiString (Font_FontMgr_MapOfFontsAliases[anIter].FontName);
664       aFontAspect = Font_FontMgr_MapOfFontsAliases[anIter].FontAspect;
665       break;
666     }
667   }
668
669   // check font family alias with specified font aspect
670   if (theFontAspect != Font_FA_Undefined
671    && theFontAspect != Font_FA_Regular
672    && theFontAspect != aFontAspect)
673   {
674     aFont = GetFont (aFontName, theFontAspect, aFontSize);
675     if (!aFont.IsNull())
676     {
677       return aFont;
678     }
679   }
680
681   // check font alias with aspect in the name
682   aFont = GetFont (aFontName, aFontAspect, aFontSize);
683   if (!aFont.IsNull())
684   {
685     return aFont;
686   }
687
688   // Requested family name not found -> search for any font family with given aspect and height
689   aFontName = new TCollection_HAsciiString ("");
690   aFont = GetFont (aFontName, aFontAspect, aFontSize);
691   if (!aFont.IsNull())
692   {
693     return aFont;
694   }
695
696   // The last resort: trying to use ANY font available in the system
697   aFontAspect = Font_FA_Undefined;
698   aFontSize = -1;
699   aFont = GetFont (aFontName, aFontAspect, aFontSize);
700   if (!aFont.IsNull())
701   {
702     return aFont;
703   }
704
705   return NULL; // Fonts are not found in the system.
706 }