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