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