0030706: Visualization - fetch font folder list from fontconfig library on Linux
authorkgv <kgv@opencascade.com>
Sat, 11 May 2019 07:07:19 +0000 (10:07 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 20 Jun 2019 12:20:49 +0000 (15:20 +0300)
vfont command now prints fonts in alphabetical order.

adm/cmake/occt_csf.cmake
adm/genproj.tcl
adm/qmake/OccToolkit.pri
src/Font/Font_FontMgr.cxx
src/TKService/EXTERNLIB
src/ViewerTest/ViewerTest_ObjectCommands.cxx

index 025499a..acb3426 100644 (file)
@@ -73,7 +73,7 @@ if (WIN32)
     set (CSF_OpenGlLibs  "opengl32.lib")
   endif()
 
-  else()
+else()
 
   if (APPLE)
     set (CSF_objc        "objc")
@@ -117,5 +117,6 @@ if (WIN32)
     endif()
     set (CSF_XwLibs      "X11 Xext Xmu Xi")
     set (CSF_dl          "dl")
+    set (CSF_fontconfig  "fontconfig")
   endif()
 endif()
index 0612e47..51af053 100644 (file)
@@ -1393,6 +1393,7 @@ proc osutils:csfList { theOS theCsfLibsMap theCsfFrmsMap } {
       set aLibsMap(CSF_TclTkLibs)  ""
       set aLibsMap(CSF_QT)         "QtCore QtGui"
     } else {
+      set aLibsMap(CSF_fontconfig) "fontconfig"
       if { "$theOS" == "qnx" } {
         # CSF_ThreadLibs - pthread API is part of libc on QNX
         set aLibsMap(CSF_OpenGlLibs) "EGL GLESv2"
index 385b77d..7d59a29 100644 (file)
@@ -63,6 +63,7 @@ win32 {
   CSF_TclTkLibs  = -lX11 -ltk8.6
   CSF_XwLibs     = -lX11 -lXext -lXmu -lXi
   CSF_MotifLibs  = -lX11
+  CSF_fontconfig = -lfontconfig
   HAVE_GLES2 { CSF_OpenGlLibs = -lEGL -lGLESv2 }
 }
 
index 3fef8bd..4fad2f6 100644 (file)
@@ -88,6 +88,10 @@ IMPLEMENT_STANDARD_RTTIEXT(Font_FontMgr,Standard_Transient)
                                                    "/usr/X11/lib/X11/fs/config",
                                                    NULL
                                                   };
+
+    // Although fontconfig library can be built for various platforms,
+    // practically it is useful only on desktop Linux distributions, where it is always packaged.
+    #include <fontconfig/fontconfig.h>
   #endif
 
   #ifdef __APPLE__
@@ -393,7 +397,7 @@ Standard_Boolean Font_FontMgr::RegisterFont (const Handle(Font_SystemFont)& theF
 void Font_FontMgr::InitFontDataBase()
 {
   myFontMap.Clear();
-  Handle(Font_FTLibrary) aFtLibrary;
+  Handle(Font_FTLibrary) aFtLibrary = new Font_FTLibrary();
 
 #if defined(OCCT_UWP)
   // system font files are not accessible
@@ -428,7 +432,6 @@ void Font_FontMgr::InitFontDataBase()
     aSupportedExtensions.Add (TCollection_AsciiString (anExt));
   }
 
-  aFtLibrary = new Font_FTLibrary();
   static const DWORD aBufferSize = 256;
   char aNameBuff[aBufferSize];
   char aPathBuff[aBufferSize];
@@ -471,61 +474,86 @@ void Font_FontMgr::InitFontDataBase()
 
   NCollection_Map<TCollection_AsciiString> aMapOfFontsDirs;
 #if !defined(__ANDROID__) && !defined(__APPLE__)
-  const OSD_Protection aProtectRead (OSD_R, OSD_R, OSD_R, OSD_R);
-
-  // read fonts directories from font service config file (obsolete)
-  for (Standard_Integer anIter = 0; myFontServiceConf[anIter] != NULL; ++anIter)
+  if (FcConfig* aFcCfg = FcInitLoadConfig())
   {
-    const TCollection_AsciiString aFileOfFontsPath (myFontServiceConf[anIter]);
-    OSD_File aFile (aFileOfFontsPath);
-    if (!aFile.Exists())
+    if (FcStrList* aFcFontDir = FcConfigGetFontDirs (aFcCfg))
     {
-      continue;
-    }
+      for (;;)
+      {
+        FcChar8* aFcFolder = FcStrListNext (aFcFontDir);
+        if (aFcFolder == NULL)
+        {
+          break;
+        }
 
-    aFile.Open (OSD_ReadOnly, aProtectRead);
-    if (!aFile.IsOpen())
-    {
-      continue;
+        TCollection_AsciiString aPathStr ((const char* )aFcFolder);
+        OSD_Path aPath (aPathStr);
+        addDirsRecursively (aPath, aMapOfFontsDirs);
+      }
+      FcStrListDone (aFcFontDir);
     }
+    FcConfigDestroy (aFcCfg);
+  }
 
-    Standard_Integer aNByte = 256;
-    Standard_Integer aNbyteRead;
-    TCollection_AsciiString aStr; // read string with information
-    while (!aFile.IsAtEnd())
+  const OSD_Protection aProtectRead (OSD_R, OSD_R, OSD_R, OSD_R);
+  if (aMapOfFontsDirs.IsEmpty())
+  {
+    Message::DefaultMessenger()->Send ("Font_FontMgr, fontconfig library returns an empty folder list", Message_Alarm);
+
+    // read fonts directories from font service config file (obsolete)
+    for (Standard_Integer anIter = 0; myFontServiceConf[anIter] != NULL; ++anIter)
     {
-      Standard_Integer aLocation = -1;
-      Standard_Integer aPathLocation = -1;
+      const TCollection_AsciiString aFileOfFontsPath (myFontServiceConf[anIter]);
+      OSD_File aFile (aFileOfFontsPath);
+      if (!aFile.Exists())
+      {
+        continue;
+      }
 
-      aFile.ReadLine (aStr, aNByte, aNbyteRead); // reading 1 line (256 bytes)
-      aLocation = aStr.Search ("catalogue=");
-      if (aLocation < 0)
+      aFile.Open (OSD_ReadOnly, aProtectRead);
+      if (!aFile.IsOpen())
       {
-        aLocation = aStr.Search ("catalogue =");
+        continue;
       }
 
-      aPathLocation = aStr.Search ("/");
-      if (aLocation > 0 && aPathLocation > 0)
+      Standard_Integer aNByte = 256;
+      Standard_Integer aNbyteRead;
+      TCollection_AsciiString aStr; // read string with information
+      while (!aFile.IsAtEnd())
       {
-        aStr = aStr.Split (aPathLocation - 1);
-        TCollection_AsciiString aFontPath;
-        Standard_Integer aPathNumber = 1;
-        do
+        Standard_Integer aLocation = -1;
+        Standard_Integer aPathLocation = -1;
+
+        aFile.ReadLine (aStr, aNByte, aNbyteRead); // reading 1 line (256 bytes)
+        aLocation = aStr.Search ("catalogue=");
+        if (aLocation < 0)
+        {
+          aLocation = aStr.Search ("catalogue =");
+        }
+
+        aPathLocation = aStr.Search ("/");
+        if (aLocation > 0 && aPathLocation > 0)
         {
-          // Getting directory paths, which can be splitted by "," or ":"
-          aFontPath = aStr.Token (":,", aPathNumber);
-          aFontPath.RightAdjust();
-          if (!aFontPath.IsEmpty())
+          aStr = aStr.Split (aPathLocation - 1);
+          TCollection_AsciiString aFontPath;
+          Standard_Integer aPathNumber = 1;
+          do
           {
-            OSD_Path aPath(aFontPath);
-            addDirsRecursively (aPath, aMapOfFontsDirs);
+            // Getting directory paths, which can be splitted by "," or ":"
+            aFontPath = aStr.Token (":,", aPathNumber);
+            aFontPath.RightAdjust();
+            if (!aFontPath.IsEmpty())
+            {
+              OSD_Path aPath(aFontPath);
+              addDirsRecursively (aPath, aMapOfFontsDirs);
+            }
+            aPathNumber++;
           }
-          aPathNumber++;
+          while (!aFontPath.IsEmpty());
         }
-        while (!aFontPath.IsEmpty());
       }
+      aFile.Close();
     }
-    aFile.Close();
   }
 #endif
 
@@ -545,7 +573,6 @@ void Font_FontMgr::InitFontDataBase()
     aSupportedExtensions.Add (TCollection_AsciiString (anExt));
   }
 
-  aFtLibrary = new Font_FTLibrary();
   for (NCollection_Map<TCollection_AsciiString>::Iterator anIter (aMapOfFontsDirs);
        anIter.More(); anIter.Next())
   {
index bcfd022..b5d8d72 100755 (executable)
@@ -14,6 +14,7 @@ CSF_user32
 CSF_XwLibs
 CSF_dpsLibs
 CSF_XmuLibs
+CSF_fontconfig
 CSF_objc
 CSF_Appkit
 CSF_IOKit
index c3d2b9c..1f88123 100644 (file)
@@ -5451,6 +5451,14 @@ static int TextToBRep (Draw_Interpretor& /*theDI*/,
 //function : VFont
 //purpose  : Font management
 //=======================================================================
+struct FontComparator
+{
+  bool operator() (const Handle(Font_SystemFont)& theFontA,
+                   const Handle(Font_SystemFont)& theFontB)
+  {
+    return theFontA->FontKey().IsLess (theFontB->FontKey());
+  }
+};
 
 static int VFont (Draw_Interpretor& theDI,
                   Standard_Integer  theArgNb,
@@ -5462,9 +5470,16 @@ static int VFont (Draw_Interpretor& theDI,
     // just print the list of available fonts
     Standard_Boolean isFirst = Standard_True;
     const Font_NListOfSystemFont aFonts = aMgr->GetAvailableFonts();
-    for (Font_NListOfSystemFont::Iterator anIter (aFonts); anIter.More(); anIter.Next())
+    std::vector<Handle(Font_SystemFont)> aFontsSorted;
+    aFontsSorted.reserve (aFonts.Size());
+    for (Font_NListOfSystemFont::Iterator aFontIter (aFonts); aFontIter.More(); aFontIter.Next())
+    {
+      aFontsSorted.push_back (aFontIter.Value());
+    }
+    std::stable_sort (aFontsSorted.begin(), aFontsSorted.end(), FontComparator());
+    for (std::vector<Handle(Font_SystemFont)>::iterator aFontIter = aFontsSorted.begin(); aFontIter != aFontsSorted.end(); ++aFontIter)
     {
-      const Handle(Font_SystemFont)& aFont = anIter.Value();
+      const Handle(Font_SystemFont)& aFont = *aFontIter;
       if (!isFirst)
       {
         theDI << "\n";