1 // Created on: 2008-01-20
2 // Created by: Alexander A. BORODIN
3 // Copyright (c) 2008-2012 OPEN CASCADE SAS
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.
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.
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.
20 #include <Font_FontMgr.ixx>
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>
30 #include FT_FREETYPE_H
32 struct Font_FontMgr_FontAliasMapNode
34 const char * EnumName;
35 const char * FontName;
36 Font_FontAspect FontAspect;
39 static const Font_FontMgr_FontAliasMapNode Font_FontMgr_MapOfFontsAliases[] =
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 }
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 }
72 #define NUM_FONT_ENTRIES (int)(sizeof(Font_FontMgr_MapOfFontsAliases)/sizeof(Font_FontMgr_FontAliasMapNode))
74 #if (defined(_WIN32) || defined(__WIN32__))
80 #pragma comment (lib, "freetype.lib")
86 // list of supported extensions
87 static Standard_CString Font_FontMgr_Extensions[] =
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>
108 // list of supported extensions
109 static Standard_CString Font_FontMgr_Extensions[] =
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",
127 // default fonts paths in Mac OS X
128 static Standard_CString myDefaultFontsDirs[] = {"/System/Library/Fonts",
133 // default fonts paths in most Unix systems (Linux and others)
134 static Standard_CString myDefaultFontsDirs[] = {"/usr/share/fonts",
135 "/usr/local/share/fonts",
140 static void addDirsRecursively (const OSD_Path& thePath,
141 NCollection_Map<TCollection_AsciiString>& theDirsMap)
143 TCollection_AsciiString aDirName;
144 thePath.SystemName (aDirName);
145 if (!theDirsMap.Add (aDirName))
150 for (OSD_DirectoryIterator aDirIterator (thePath, "*"); aDirIterator.More(); aDirIterator.Next())
152 OSD_Path aChildDirPath;
153 aDirIterator.Values().Path (aChildDirPath);
155 TCollection_AsciiString aChildDirName;
156 aChildDirPath.SystemName (aChildDirName);
157 if (!aChildDirName.IsEqual (".") && !aChildDirName.IsEqual (".."))
159 aChildDirName = aDirName + "/" + aChildDirName;
160 OSD_Path aPath (aChildDirName);
161 addDirsRecursively (aPath, theDirsMap);
170 // =======================================================================
171 // function : checkFont
173 // =======================================================================
174 static Handle(Font_SystemFont) checkFont (const Handle(Font_FTLibrary)& theFTLib,
175 const Standard_CString theFontPath)
178 FT_Error aFaceError = FT_New_Face (theFTLib->Instance(), theFontPath, 0, &aFontFace);
179 if (aFaceError != FT_Err_Ok)
184 Font_FontAspect anAspect = Font_FA_Regular;
185 if (aFontFace->style_flags == (FT_STYLE_FLAG_ITALIC | FT_STYLE_FLAG_BOLD))
187 anAspect = Font_FA_BoldItalic;
189 else if (aFontFace->style_flags == FT_STYLE_FLAG_ITALIC)
191 anAspect = Font_FA_Italic;
193 else if (aFontFace->style_flags == FT_STYLE_FLAG_BOLD)
195 anAspect = Font_FA_Bold;
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);
202 FT_Done_Face (aFontFace);
207 // =======================================================================
208 // function : GetInstance
210 // =======================================================================
211 Handle(Font_FontMgr) Font_FontMgr::GetInstance()
213 static Handle(Font_FontMgr) _mgr;
216 _mgr = new Font_FontMgr();
222 // =======================================================================
223 // function : Font_FontMgr
225 // =======================================================================
226 Font_FontMgr::Font_FontMgr()
231 // =======================================================================
232 // function : CheckFont
234 // =======================================================================
235 Handle(Font_SystemFont) Font_FontMgr::CheckFont (Standard_CString theFontPath) const
237 Handle(Font_FTLibrary) aFtLibrary = new Font_FTLibrary();
238 return checkFont (aFtLibrary, theFontPath);
241 // =======================================================================
242 // function : RegisterFont
244 // =======================================================================
245 Standard_Boolean Font_FontMgr::RegisterFont (const Handle(Font_SystemFont)& theFont,
246 const Standard_Boolean theToOverride)
248 if (theFont.IsNull())
250 return Standard_False;
253 for (Font_NListOfSystemFont::Iterator aFontIter (myListOfFonts);
254 aFontIter.More(); aFontIter.Next())
256 if (!aFontIter.Value()->FontName()->IsSameString (theFont->FontName(), Standard_False))
261 if (theFont->FontAspect() != Font_FA_Undefined
262 && aFontIter.Value()->FontAspect() != theFont->FontAspect())
267 if (theFont->FontHeight() == -1 || aFontIter.Value()->FontHeight() == -1
268 || theFont->FontHeight() == aFontIter.Value()->FontHeight())
270 if (theFont->FontPath()->String() == aFontIter.Value()->FontPath()->String())
272 return Standard_True;
274 else if (theToOverride)
276 myListOfFonts.Remove (aFontIter);
280 return Standard_False;
285 myListOfFonts.Append (theFont);
286 return Standard_True;
289 // =======================================================================
290 // function : InitFontDataBase
292 // =======================================================================
293 void Font_FontMgr::InitFontDataBase()
295 myListOfFonts.Clear();
296 Handle(Font_FTLibrary) aFtLibrary;
300 // font directory is placed in "C:\Windows\Fonts\"
301 UINT aStrLength = GetSystemWindowsDirectoryA (NULL, 0);
307 char* aWinDir = new char[aStrLength];
308 GetSystemWindowsDirectoryA (aWinDir, aStrLength);
309 Handle(TCollection_HAsciiString) aFontsDir = new TCollection_HAsciiString (aWinDir);
310 aFontsDir->AssignCat ("\\Fonts\\");
313 // read fonts list from registry
315 if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts",
316 0, KEY_READ, &aFontsKey) != ERROR_SUCCESS)
321 NCollection_Map<TCollection_AsciiString> aSupportedExtensions;
322 for (Standard_Integer anIter = 0; Font_FontMgr_Extensions[anIter] != NULL; ++anIter)
324 Standard_CString anExt = Font_FontMgr_Extensions[anIter];
325 aSupportedExtensions.Add (TCollection_AsciiString (anExt));
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)
340 aPathBuff[(aPathSize < aBufferSize) ? aPathSize : (aBufferSize - 1)] = '\0'; // ensure string is NULL-terminated
342 Handle(TCollection_HAsciiString) aFontName = new TCollection_HAsciiString (aNameBuff);
343 Handle(TCollection_HAsciiString) aFontPath = new TCollection_HAsciiString (aPathBuff);
344 if (aFontPath->Search ("\\") == -1)
346 aFontPath->Insert (1, aFontsDir); // make absolute path
349 // check file extension is in list of supported
350 const Standard_Integer anExtensionPosition = aFontPath->SearchFromEnd (".") + 1;
351 if (anExtensionPosition > 0 && anExtensionPosition < aFontPath->Length())
353 Handle(TCollection_HAsciiString) aFontExtension = aFontPath->SubString (anExtensionPosition, aFontPath->Length());
354 aFontExtension->LowerCase();
355 if (aSupportedExtensions.Contains (aFontExtension->String()))
357 Handle(Font_SystemFont) aNewFont = checkFont (aFtLibrary, aFontPath->ToCString());
358 if (!aNewFont.IsNull())
360 myListOfFonts.Append (aNewFont);
366 // close registry key
367 RegCloseKey (aFontsKey);
371 NCollection_Map<TCollection_AsciiString> aMapOfFontsDirs;
372 const OSD_Protection aProtectRead (OSD_R, OSD_R, OSD_R, OSD_R);
374 // read fonts directories from font service config file (obsolete)
375 for (Standard_Integer anIter = 0; myFontServiceConf[anIter] != NULL; ++anIter)
377 const TCollection_AsciiString aFileOfFontsPath (myFontServiceConf[anIter]);
378 OSD_File aFile (aFileOfFontsPath);
384 aFile.Open (OSD_ReadOnly, aProtectRead);
390 Standard_Integer aNByte = 256;
391 Standard_Integer aNbyteRead;
392 TCollection_AsciiString aStr; // read string with information
393 while (!aFile.IsAtEnd())
395 Standard_Integer aLocation = -1;
396 Standard_Integer aPathLocation = -1;
398 aFile.ReadLine (aStr, aNByte, aNbyteRead); // reading 1 line (256 bytes)
399 aLocation = aStr.Search ("catalogue=");
402 aLocation = aStr.Search ("catalogue =");
405 aPathLocation = aStr.Search ("/");
406 if (aLocation > 0 && aPathLocation > 0)
408 aStr = aStr.Split (aPathLocation - 1);
409 TCollection_AsciiString aFontPath;
410 Standard_Integer aPathNumber = 1;
413 // Getting directory paths, which can be splitted by "," or ":"
414 aFontPath = aStr.Token (":,", aPathNumber);
415 aFontPath.RightAdjust();
416 if (!aFontPath.IsEmpty())
418 OSD_Path aPath(aFontPath);
419 addDirsRecursively (aPath, aMapOfFontsDirs);
423 while (!aFontPath.IsEmpty());
429 // append default directories
430 for (Standard_Integer anIter = 0; myDefaultFontsDirs[anIter] != NULL; ++anIter)
432 Standard_CString anItem = myDefaultFontsDirs[anIter];
433 TCollection_AsciiString aPathStr (anItem);
434 OSD_Path aPath (aPathStr);
435 addDirsRecursively (aPath, aMapOfFontsDirs);
438 NCollection_Map<TCollection_AsciiString> aSupportedExtensions;
439 for (Standard_Integer anIter = 0; Font_FontMgr_Extensions[anIter] != NULL; ++anIter)
441 Standard_CString anExt = Font_FontMgr_Extensions[anIter];
442 aSupportedExtensions.Add (TCollection_AsciiString (anExt));
445 aFtLibrary = new Font_FTLibrary();
446 for (NCollection_Map<TCollection_AsciiString>::Iterator anIter (aMapOfFontsDirs);
447 anIter.More(); anIter.Next())
449 OSD_File aReadFile (anIter.Value() + "/fonts.dir");
450 if (!aReadFile.Exists())
452 continue; // invalid fonts directory
455 aReadFile.Open (OSD_ReadOnly, aProtectRead);
456 if (!aReadFile.IsOpen())
458 continue; // invalid fonts directory
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())
467 aReadFile.ReadLine (aLine, aNByte, aNbyteRead);
470 // first line contains the number of fonts in this file
471 // just ignoring it...
472 isFirstLine = Standard_False;
476 Standard_Integer anExtensionPosition = aLine.Search (".") + 1;
477 if (anExtensionPosition == 0)
479 continue; // can't find extension position in the font description
482 Standard_Integer anEndOfFileName = aLine.Location (" ", anExtensionPosition, aLine.Length()) - 1;
483 if (anEndOfFileName < 0 || anEndOfFileName < anExtensionPosition)
485 continue; // font description have empty extension
488 TCollection_AsciiString aFontExtension = aLine.SubString (anExtensionPosition, anEndOfFileName);
489 aFontExtension.LowerCase();
490 if (aSupportedExtensions.Contains (aFontExtension) && (aLine.Search (anEncoding) > 0))
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())
501 aFontPath->AssignCat ("/");
503 Handle(TCollection_HAsciiString) aFontFileName =
504 new TCollection_HAsciiString (aLine.SubString (1, anEndOfFileName));
505 aFontPath->AssignCat (aFontFileName);
507 Handle(Font_SystemFont) aNewFontFromXLFD = new Font_SystemFont (aXLFD, aFontPath);
508 Handle(Font_SystemFont) aNewFont = checkFont (aFtLibrary, aFontPath->ToCString());
510 if (aNewFontFromXLFD->IsValid() && !aNewFont.IsNull() &&
511 !aNewFont->IsEqual (aNewFontFromXLFD))
513 myListOfFonts.Append (aNewFont);
514 myListOfFonts.Append (aNewFontFromXLFD);
516 else if (!aNewFont.IsNull())
518 myListOfFonts.Append (aNewFont);
520 else if (aNewFontFromXLFD->IsValid())
522 myListOfFonts.Append (aNewFontFromXLFD);
532 // =======================================================================
533 // function : GetAvailableFonts
535 // =======================================================================
536 const Font_NListOfSystemFont& Font_FontMgr::GetAvailableFonts() const
538 return myListOfFonts;
541 // =======================================================================
542 // function : GetAvailableFontsNames
544 // =======================================================================
545 void Font_FontMgr::GetAvailableFontsNames (TColStd_SequenceOfHAsciiString& theFontsNames) const
547 theFontsNames.Clear();
548 for (Font_NListOfSystemFont::Iterator anIter(myListOfFonts); anIter.More(); anIter.Next())
550 theFontsNames.Append (anIter.Value()->FontName());
554 // =======================================================================
555 // function : GetFont
557 // =======================================================================
558 Handle(Font_SystemFont) Font_FontMgr::GetFont (const Handle(TCollection_HAsciiString)& theFontName,
559 const Font_FontAspect theFontAspect,
560 const Standard_Integer theFontSize) const
562 if ( (theFontSize < 2 && theFontSize != -1) || theFontName.IsNull())
567 for (Font_NListOfSystemFont::Iterator aFontsIterator (myListOfFonts);
568 aFontsIterator.More(); aFontsIterator.Next())
570 if (!theFontName->IsEmpty() && !aFontsIterator.Value()->FontName()->IsSameString (theFontName, Standard_False))
575 if (theFontAspect != Font_FA_Undefined && aFontsIterator.Value()->FontAspect() != theFontAspect)
580 if (theFontSize == -1 || aFontsIterator.Value()->FontHeight() == -1 ||
581 theFontSize == aFontsIterator.Value()->FontHeight())
583 return aFontsIterator.Value();
590 // =======================================================================
591 // function : FindFont
593 // =======================================================================
594 Handle(Font_SystemFont) Font_FontMgr::FindFont (const Handle(TCollection_HAsciiString)& theFontName,
595 const Font_FontAspect theFontAspect,
596 const Standard_Integer theFontSize) const
598 Handle(TCollection_HAsciiString) aFontName = theFontName;
599 Font_FontAspect aFontAspect = theFontAspect;
600 Standard_Integer aFontSize = theFontSize;
602 Handle(Font_SystemFont) aFont = GetFont (aFontName, aFontAspect, aFontSize);
608 // Trying to use font names mapping
609 for (Standard_Integer anIter = 0; anIter < NUM_FONT_ENTRIES; ++anIter)
611 Handle(TCollection_HAsciiString) aFontAlias =
612 new TCollection_HAsciiString (Font_FontMgr_MapOfFontsAliases[anIter].EnumName);
614 if (aFontAlias->IsSameString (aFontName, Standard_False))
616 aFontName = new TCollection_HAsciiString (Font_FontMgr_MapOfFontsAliases[anIter].FontName);
617 aFontAspect = Font_FontMgr_MapOfFontsAliases[anIter].FontAspect;
622 // check font family alias with specified font aspect
623 if (theFontAspect != Font_FA_Undefined
624 && theFontAspect != Font_FA_Regular
625 && theFontAspect != aFontAspect)
627 aFont = GetFont (aFontName, theFontAspect, aFontSize);
634 // check font alias with aspect in the name
635 aFont = GetFont (aFontName, aFontAspect, aFontSize);
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);
649 // The last resort: trying to use ANY font available in the system
650 aFontAspect = Font_FA_Undefined;
652 aFont = GetFont (aFontName, aFontAspect, aFontSize);
658 return NULL; // Fonts are not found in the system.