ecere/gfx/fontManagement: Listing fonts with Fontconfig
[sdk] / ecere / src / gfx / fontManagement.ec
index 84c73e5..d811a60 100644 (file)
@@ -27,7 +27,7 @@ static int CALLBACK MyFontProc(ENUMLOGFONTEX * font, NEWTEXTMETRICEX *lpntme, in
    //if(fontType == TRUETYPE_FONTTYPE)
    {
       FontData * fontData = (FontData *) lParam;
-      char * fileName = (char *)lParam;
+      char * fileName = fontData->fileName;
       HKEY key;
       int weight = (fontData->flags.bold) ? FW_BOLD : FW_NORMAL;
       int italic = (fontData->flags.italic) ? 1 : 0;
@@ -304,13 +304,16 @@ public Array<FaceInfo> ResolveFont(const String faceName, float size, FontFlags
 #endif
       while(true)
       {
-         FaceInfo faceInfo
+         if(FileExists(fileName))
          {
-            fileName = CopyString(fileName),
-            fakeItalic = fakeItalic,
-            fontID = fontID
-         };
-         fileNames.Add(faceInfo);
+            FaceInfo faceInfo
+            {
+               fileName = CopyString(fileName),
+               fakeItalic = fakeItalic,
+               fontID = fontID
+            };
+            fileNames.Add(faceInfo);
+         }
          {
             int c;
             char ch;
@@ -394,9 +397,94 @@ public Array<FaceInfo> ResolveFont(const String faceName, float size, FontFlags
 #endif
 
 #endif
+   if(!fileNames.count)
+      delete fileNames;
    return fileNames;
 }
 
+import "AVLTree"
+
+public struct FontInfo
+{
+   bool fixedPitch;
+   bool defaultOrAnsiCharSet;
+};
+
+#if defined(__WIN32__)
+static int CALLBACK fontLister(ENUMLOGFONTEXW * font, NEWTEXTMETRICEX *lpntme, int fontType, LPARAM lParam)
+{
+   // const String faceName = font->elfLogFont.lfFaceName;
+   uint16 * faceName = font->elfLogFont.lfFaceName;
+   String s = UTF16toUTF8(faceName);
+   if(s[0] != '@')
+   {
+      Map<String, FontInfo> fonts = (Map<String, FontInfo>)lParam;
+      MapIterator<String, FontInfo> it { map = fonts };
+      if(!it.Index(s, true))
+         it.data = { (font->elfLogFont.lfPitchAndFamily & 3) == FIXED_PITCH, defaultOrAnsiCharSet = (font->elfLogFont.lfCharSet == ANSI_CHARSET || font->elfLogFont.lfCharSet == DEFAULT_CHARSET) };
+   }
+   delete s;
+   return 1;
+}
+#endif
+
+public Map<String, FontInfo> ListAvailableFonts()
+{
+   Map<String, FontInfo> fonts { };
+
+#if defined(__WIN32__)
+   LOGFONTW logFont = { 0 };
+   HDC hdc = GetDC(0);
+   logFont.lfCharSet = DEFAULT_CHARSET;
+
+   EnumFontFamiliesExW(hdc, &logFont, (void *)fontLister, (LPARAM)fonts, 0);
+
+   ReleaseDC(0, hdc);
+#elif !defined(ECERE_NOFONTCONFIG)
+   int i;
+   FcPattern * pattern;
+   FcObjectSet * objectSet;
+   FcFontSet * fontSet;
+
+   if(!fcConfig)
+      fcConfig = FcInitLoadConfigAndFonts();
+
+   pattern = FcPatternCreate();
+   objectSet = FcObjectSetBuild(FC_FAMILY, FC_SPACING, FC_CHARSET, null);
+   fontSet = FcFontList(fcConfig, pattern, objectSet);
+   if(fontSet)
+   {
+      MapIterator<String, FontInfo> it { map = fonts };
+      for(i = 0; i < fontSet->nfont; i++)
+      {
+         FcPattern * font = fontSet->fonts[i];
+         String family;
+         int spacing;
+         FcCharSet * charSet;
+
+         if(FcPatternGetString(font, FC_FAMILY, 0, (byte **)&family) == FcResultMatch &&
+            FcPatternGetInteger(font, FC_SPACING, 0, &spacing) == FcResultMatch &&
+            FcPatternGetCharSet(font, FC_CHARSET, 0, &charSet) == FcResultMatch)
+         {
+            if(!it.Index(family, true))
+            {
+               it.data =
+               {
+                  fixedPitch = spacing == FC_MONO,
+                  defaultOrAnsiCharSet =
+                     FcCharSetHasChar(charSet, '[') && FcCharSetHasChar(charSet, '{') &&
+                     FcCharSetHasChar(charSet, 'a') && FcCharSetHasChar(charSet, 'Z');
+               };
+            }
+         }
+      }
+   }
+   if(pattern) FcPatternDestroy(pattern);
+   if(fontSet) FcFontSetDestroy(fontSet);
+#endif
+   return fonts;
+}
+
 public FaceInfo ResolveCharFont(const String faceName, float size, FontFlags flags, const String lang, unichar testChar)
 {
    FaceInfo info = null;
@@ -453,6 +541,14 @@ public FaceInfo ResolveCharFont(const String faceName, float size, FontFlags fla
    if(pattern) FcPatternDestroy(pattern);
    if(matched) FcPatternDestroy(matched);
    if(charSet) FcCharSetDestroy(charSet);
+#elif defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
+   {
+      // Fall back to Arial Unicode MS
+      char fileName[MAX_LOCATION];
+      GetWindowsDirectory(fileName, MAX_LOCATION);
+      PathCat(fileName, "fonts/arialuni.ttf");
+      info = { fileName = CopyString(fileName) };
+   }
 #endif
    return info;
 }